How does this setter end up working? (ListView MultiSelect)

别来无恙 提交于 2019-12-24 15:53:31

问题


I have a ViewModel which I'm using as an ItemsSource for a ListView, that implements an interface called ISelectable:

/// <summary>
/// An interface that should be implemented by a ViewModel that can be 
/// marked as selected, when multiple selections are allowed.
/// </summary>
public interface ISelectable
{
    /// <summary>
    /// Gets or sets a value indicating whether this instance is selected.
    /// </summary>
    /// <value>
    /// <c>true</c> if this instance is selected; otherwise, <c>false</c>.
    /// </value>
    bool IsSelected { get; set; }
}

The ListView is showing search results of a "search clients" feature, so all items are ClientViewModel instances - and ClientViewModel implements ISelectable so has a IsSelected property:

<ListView x:Name="SearchResultsList" ItemsSource="{Binding SearchResults}">
    <ListView.ItemContainerStyle>
        <Style TargetType="ListViewItem">
            <Setter Property="IsSelected" Value="{Binding IsSelected}" />
        </Style>
    </ListView.ItemContainerStyle>
    <ListView.ItemTemplate>
        <DataTemplate DataType="{x:Type viewModels:ClientViewModel}">
            <Label Content="{Binding Name}" />
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

This works perfectly; in the window's ViewModel I can define a property like this:

public IEnumerable<ClientViewModel> SelectedClients 
{ 
    get 
    { 
        return _searchResults == null 
                              ? null 
                              : _searchResults.Where(e => e.IsSelected); 
    } 
}

And I get what I'm expecting.

The question I have is about the below part of the XAML - the designer underlines IsSelected in the Value="{Binding}" part and says "Cannot resolve property 'IsSelected' in data context of type [type of the window's ViewModel]":

    <ListView.ItemContainerStyle>
        <Style TargetType="ListViewItem">
            <Setter Property="IsSelected" Value="{Binding IsSelected}" />
        </Style>
    </ListView.ItemContainerStyle>
  • How can I tell the designer that the data context for ListView.ItemContainerStyle should be the same as that of the data template?
  • How does it end up working at run-time, if the XAML designer says it can't be resolved?

UPDATE

This is a ReSharper warning. I could switch it off, but what I want to know is how does the setter end up working, because I get correct auto-complete for this:

    <ListView.ItemTemplate>
        <DataTemplate DataType="{x:Type viewModels:ClientViewModel}">
            <Label Content="{Binding Name}" /> <!-- "Name" is available from IntelliSense -->
        </DataTemplate>
    </ListView.ItemTemplate>

But not for that:

    <ListView.ItemContainerStyle>
        <Style TargetType="ListViewItem">
            <Setter Property="IsSelected" Value="{Binding IsSelected}" /> 
            <!-- "IsSelected" isn't, IntelliSense is showing the members of the Window's ViewModel -->
        </Style>
    </ListView.ItemContainerStyle>

回答1:


It should be the Resharper doing the trick as i never saw default designer intellisense pointing this type of error in Binding experssion. You can switch of the Resharper completly to proof it completly.

since you are setting property inside ListViewItem style and you are using {Binding IsSelected}, it will search IsSelected in the DataContext of each listviewitem which is your ClientViewModel and that has IsSelected property...hence binding is perfect.. the designer is not smart enough to prob this deep



来源:https://stackoverflow.com/questions/19100882/how-does-this-setter-end-up-working-listview-multiselect

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!