【问题标题】:Why the databinding fails in ListView (WPF)?为什么 ListView (WPF) 中的数据绑定失败?
【发布时间】:2010-05-17 05:33:10
【问题描述】:

我有一个 ListView,其中 ItemSource 设置为我的自定义集合。

我已经定义了一个包含组合框的 GridView CellTemplate,如下所示:

           <ListView
            MaxWidth="850"                
            Grid.Row="1"
            SelectedItem="{Binding Path = SelectedCondition}"
            ItemsSource="{Binding Path = Conditions}"                 
            FontWeight="Normal"
            FontSize="11"                                
            Name="listview">
            <ListView.View>
                <GridView>
                    <GridViewColumn                           
                        Width="175"
                        Header="Type">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <ComboBox                                       
                                    Style="{x:Null}"
                                    x:Name="TypeCmbox"
                                    Height="Auto"
                                    Width="150"
                                    SelectedValuePath="Key"
                                    DisplayMemberPath="Value"    
                                    SelectedItem="{Binding Path = MyType}"
                                    ItemsSource="{Binding Path = MyTypes}"
                                    HorizontalAlignment="Center" />
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
              </ListView>


public MyType : INotifyPropertyChanged

{ 字符串键; 字符串值;

public string Key { get { return _key; }
    set { _key = value; this.OnPropertyChanged("Key"); } }

public string Value { get { return _value; } 
    set { _value = value; this.OnPropertyChanged("Value"); } }

    public MyType ()
    {


    }

    public MyType (string key, string value)
    {
        _key = key;
        _value = value;
    }

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = this.PropertyChanged;
        if (handler != null)
            handler(this, new PropertyChangedEventArgs(propertyName));
    }


    #endregion

}

 public void MoveUpExecuted()
    {
        int oldIndex = this.Conditions.IndexOf(_selectedCondition);

       //Check if the selected item is not the first item
        if (oldIndex != 0)
        {
            int newIndex = oldIndex - 1;
            this.Conditions.Move(oldIndex, newIndex);

        }           
    }

我的自定义集合是 ObservableCollection。

我在 listview 控件顶部有两个按钮 - Move Up 和 Move Down。当用户点击 Move Up 或 Move Down 按钮时,我调用 Observable Collection 的 Move 方法。

但是当我向上移动和向下移动行时,组合框的选定索引为-1。

在执行上移和下移命令时,我已确保 selectedItem 不等于 null。

请帮忙!!

【问题讨论】:

    标签: wpf data-binding


    【解决方案1】:

    我不明白这部分:

    我调用 MoveUp 和 MoveDown 方法 可观察的集合。

    ObservableCollection 没有这样的方法,至少据我所知没有?它也没有当前项目或类似项目的概念。

    如果我错过了一些可能会使这篇文章变得无知的东西,我深表歉意。

    您可以做的不是将 ListView 绑定到 ObservableCollection,而是将其绑定到 ICollectionView(派生自 ObservableCollection)。如果在ListView上设置IsSynchronizedWithCurrentItem=True,则不需要绑定SelectedItem,它会自动绑定到ICollectionView上的CurrentItem。

    ICollectionView 还实现了 MoveCurrentToNext 和 MoveCurrentCurrentToPrevious,可以从您的按钮绑定(通过 ICommand)。

    编辑: 既然新信息已经摆在桌面上,我上面的答案就不再重要了。但是我(还)不知道 SO 约定如何处理这个问题,如果我应该完全删除帖子,编辑掉上面的内容或者只是添加“新”回复。现在我将编辑这篇文章。

    我试图重新创建您的项目和您的问题。希望我已经正确理解了您的问题,并且至少以类似的方式重新创建了它。

    问题是组合框在列表视图中移动时没有保持其值,它对我有用。

    以下是相关代码(其中一些隐藏以避免太多噪音)。

    这对你有帮助吗?

    public class MainWindowViewModel:INotifyPropertyChanged
        {
            private Condition _selectedCondition;
            public ObservableCollection<Condition> Conditions { get; set; }
    
            public Condition SelectedCondition
            {
                get
                {
                    return _selectedCondition;
                }
                set
                {
                    if (_selectedCondition != value)
                    {
                        _selectedCondition = value;
                        OnPropertyChanged("SelectedCondition");
                    }
                }
            }
    ...
    public void MoveUpExecuted()
        {
            int oldIndex = this.Conditions.IndexOf(_selectedCondition);
    
            //Check if the selected item is not the first item
            if (oldIndex != 0)
            {
                int newIndex = oldIndex - 1;
                this.Conditions.Move(oldIndex, newIndex);
            }
        }
    

    以及条件类:

    public class Condition : INotifyPropertyChanged
        {
            private MyType myType;
            public ObservableCollection<MyType> MyTypes { get; set; }
    
            public MyType MyType
            {
                get { return myType; }
                set
                {
                    if (myType != value)
                    {
                        myType = value;
                        OnPropertyChanged("MyType");
    
                    }
                }
            }
    
    
            public Condition()
            {
                MyTypes = new ObservableCollection<MyType>() { new MyType() { Key = "1", Value = "One" }, new MyType() { Key = "2", Value = "Two" } };
                MyType = MyTypes[1];
            }
    

    ...等

    <ListView
                SelectedItem="{Binding Path=SelectedCondition}"
                ItemsSource="{Binding Path=Conditions}"                 
                FontWeight="Normal"
                FontSize="11"                                
                Name="listview" Margin="0,32,0,0">
                <ListView.View>
                    <GridView>
                        <GridViewColumn                           
                            Width="175"
                            Header="Type">
                            <GridViewColumn.CellTemplate>
                                <DataTemplate>
                                    <ComboBox                                       
                                        Width="150"
                                        SelectedValuePath="Key"
                                        DisplayMemberPath="Value"    
                                        SelectedItem="{Binding Path=MyType}"
                                        ItemsSource="{Binding Path=MyTypes}"
                                        HorizontalAlignment="Center" />
                                </DataTemplate>
                            </GridViewColumn.CellTemplate>
                        </GridViewColumn>
                    </GridView>
                </ListView.View>
            </ListView>
            <Button Content="Move up"
                    Command="{Binding MoveUpCommand}"
                     />
    

    【讨论】:

    • 感谢您的回复。抱歉 ObservableCollection 的名称不正确,它在 ObservableCollection 中的 Move 方法将集合中的实体从旧索引移动到新索引
    • 啊,我明白了。所以,为了清楚起见,你想移动它自己的对象,就像改变项目的顺序一样,而不是像我想的那样移动选择?
    • 是的,我将 ListView 的 selectedItem 设置为移动的当前对象,从而在 listview 中提供选择
    • 我对此表示怀疑,这似乎更多地是关于是否设置了样式。你能分享一下你如何移动所选项目的代码吗?
    【解决方案2】:

    交换这些行:

    SelectedItem="{Binding Path = SelectedCondition}" 
    ItemsSource="{Binding Path = Conditions}" 
    

    ItemSource 需要在 SelectedItem 之前

    【讨论】:

    • 您是否尝试过操作 listview 上的 SelectedIndex 而不是 observableCollection 上的 Move 方法,我自己从未真正使用过它们。
    • 我尝试设置选定的 Index = 0 ( hardcoded ) ,但这也无济于事...
    【解决方案3】:

    你试过ItemsSource="{Binding Conditions}"

    【讨论】:

    • 我刚才试过了,但并没有解决问题。我仍然无法保留列表视图组合框的选定索引。
    • 一些代码会有所帮助。还可以在执行 MoveUp 操作时快速观察 MyType 属性。
    • 从您的代码中可以明显看出 MyType 是模型,而 MyTypes 是列表。但是不知道为什么要将选中的项绑定到MyType。不应该是 SelectedMyType,一个必须创建的属性吗?
    猜你喜欢
    • 1970-01-01
    • 2010-11-29
    • 2012-12-22
    • 2011-01-01
    • 2011-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-27
    相关资源
    最近更新 更多