首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >ListView SelectedItems DataBinding在MVVM中的实现

ListView SelectedItems DataBinding在MVVM中的实现
EN

Stack Overflow用户
提问于 2016-12-28 13:06:31
回答 1查看 684关注 0票数 0

我有一个问题要绑定SelectedItems of ListView控件,为了解决这个问题,我扩展了ListView控件,ListViewExtended使用这个post的引用来公开SelectedItemsList,但是双向绑定并不能在模型中获得SelectedItems。

请帮助指出这个演示源代码中的问题。

自定义控件:

代码语言:javascript
复制
public sealed class ListViewExtended : ListView
{
    public ListViewExtended()
    {
        this.SelectionChanged += ListViewExtended_SelectionChanged;
    }

    void ListViewExtended_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        this.SelectedItemsList = this.SelectedItems;
    }

    #region SelectedItemsList

    public IEnumerable SelectedItemsList
    {
        get { return (IEnumerable)GetValue(SelectedItemsListProperty); }
        set { SetValue(SelectedItemsListProperty, value); }
    }

    public static readonly DependencyProperty SelectedItemsListProperty =
            DependencyProperty.Register("SelectedItemsList",
            typeof(IEnumerable),
            typeof(ListViewExtended),
            new FrameworkPropertyMetadata(null));

    #endregion
}

模型:

代码语言:javascript
复制
public class Member
{
    public string Name { get; set; }
    public int Age { get; set; }
}

public class Family : BindableBase
{
    private string _name;
    public string Name
    {
        get { return _name; }
        set { _name = value; OnPropertyChanged("Name"); }
    }

    private IList<Member> _selectedMembers;
    public IList<Member> SelectedMembers
    {
        get { return _selectedMembers; }
        set { _selectedMembers = value; OnPropertyChanged("SelectedMembers"); }
    }

    public override string ToString()
    {
        return Name;
    }
}

ViewModel:

代码语言:javascript
复制
public class ListViewSelectedItemsExtendedViewModel : BindableBase
{
    Dictionary<string, IEnumerable> _repository = new Dictionary<string, IEnumerable>();

    public ListViewSelectedItemsExtendedViewModel()
    {
        var families = new List<Family>();
        families.Add(new Family() { Name = "family 1" });
        families.Add(new Family() { Name = "family 2" });
        Families = families;

        var items = new List<Member>();
        items.Add(new Member() { Name = "John", Age = 30 });
        items.Add(new Member() { Name = "Chapel", Age = 50 });
        items.Add(new Member() { Name = "Max", Age = 46 });
        _repository.Add(families[0].Name, items);

        items = new List<Member>();
        items.Add(new Member() { Name = "Warner", Age = 28 });
        items.Add(new Member() { Name = "Peter", Age = 36 });
        items.Add(new Member() { Name = "Tom", Age = 5 });
        _repository.Add(families[1].Name, items);
    }

    private IList<Family> _families;
    public IList<Family> Families
    {
        get { return _families; }
        set { _families = value; OnPropertyChanged("Families"); }
    }

    private Family _selectedFamily;
    public Family SelectedFamily
    {
        get { return _selectedFamily; }
        set { _selectedFamily = value; OnPropertyChanged("SelectedFamily"); }
    }

    private ICommand _familySelectionChangedCommand;
    public ICommand FamilySelectionChangedCommand
    {
        get
        {
            return _familySelectionChangedCommand ?? (_familySelectionChangedCommand = new DelegateCommand(
                () =>
                {
                    Members = (IList<Member>)_repository[SelectedFamily.Name];
                }
            ));
        }
    }
}

XAML:

代码语言:javascript
复制
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="1*" />
        <ColumnDefinition Width="3*" />
    </Grid.ColumnDefinitions>
    <ListBox ItemsSource="{Binding Families}" SelectedItem="{Binding SelectedFamily}">
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="SelectionChanged">
                <i:InvokeCommandAction Command="{Binding FamilySelectionChangedCommand}" />
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </ListBox>
    <Grid Grid.Column="1">
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <fsx:ListViewExtended Margin="10" Grid.Row="0"
                            ItemsSource="{Binding Members}" 
                            SelectedItemsList="{Binding SelectedFamily.SelectedMembers, Mode=TwoWay}">
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="Include">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <CheckBox IsChecked="{Binding Path=IsSelected, 
                                RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListViewItem}}}" />
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                    <GridViewColumn Header="Name" Width="120" DisplayMemberBinding="{Binding Name}" />
                    <GridViewColumn Header="Age" Width="50" DisplayMemberBinding="{Binding Age}" />
                </GridView>
            </ListView.View>
            <!--<i:Interaction.Behaviors>
            <fsx:ListViewMultiSelectionBehavior 
                SelectedItems="{Binding SelectedFamily.SelectedMembers}" />
        </i:Interaction.Behaviors>-->
        </fsx:ListViewExtended>
        <ListView Margin="10" Grid.Row="1" 
                ItemsSource="{Binding SelectedFamily.SelectedMembers}">
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="Name" Width="120" DisplayMemberBinding="{Binding Name}" />
                    <GridViewColumn Header="Age" Width="50" DisplayMemberBinding="{Binding Age}" />
                </GridView>
            </ListView.View>
        </ListView>
    </Grid>
</Grid>

除了上面的实现之外,我还尝试了使用这个post中给出的方法,但是没有成功地获得100%的结果。

EN

Stack Overflow用户

回答已采纳

发布于 2016-12-28 16:48:07

这里的问题是,您不能将泛型类型IList的源属性设置为非泛型IList,这是ListView的SelectedItems属性的类型。如果您自己尝试这一点,您会注意到它甚至不会编译:

代码语言:javascript
复制
IList<Member> members = listView1.SelectedItems; //WON'T COMPILE

泛型IList接口不扩展IList接口,因此这是两种完全不同的类型。这就像尝试将int属性设置为字符串一样。只是没用了。

如果您将家族类的SelectedMembers属性的类型更改为非泛型IList,它将工作:

代码语言:javascript
复制
public class Family : BindableBase
{
    private string _name;
    public string Name
    {
        get { return _name; }
        set { _name = value; OnPropertyChanged("Name"); }
    }

//change the type here:
    private IList _selectedMembers;
    public IList SelectedMembers
    {
        get { return _selectedMembers; }
        set { _selectedMembers = value; OnPropertyChanged("SelectedMembers"); }
    }

    public override string ToString()
    {
        return Name;
    }
}

必须有某种方法将其泛化,就像其他内置控件的DependencyProperty工作一样。

如前所述,为了能够将源属性设置为ListView的ListView属性的值,源属性的类型必须与SelectedItems属性的类型相匹配,即源属性应该是非泛型的IList。

您可能还想阅读以下内容:https://blog.magnusmontin.net/2014/01/30/wpf-using-behaviours-to-bind-to-readonly-properties-in-mvvm/。它是关于如何使用行为绑定到只读属性。属性的类型仍然必须匹配,尽管无论您选择采用什么解决方案。

票数 0
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41362768

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档