【问题标题】:Trouble in binding ListView.SelectedItem绑定 ListView.SelectedItem 出现问题
【发布时间】:2012-08-02 10:53:02
【问题描述】:

在我的WPF mvvm(light) 项目中,我遇到了这样的问题:在将ListView.SelectedItem 绑定到我的ModelView 之后,我试图将其从ModelView 更改。似乎没问题,但没有发生在视图:

XAML:

<ListView SelectedItem="{Binding SelectedOne}" 
          ItemsSource="{Binding Items}">
</ListView>

<ListView     ScrollViewer.CanContentScroll="False"
              ItemsSource="{Binding Items}"
              ItemTemplateSelector="{StaticResource myDataTemplateSelector}"
              HorizontalContentAlignment="Stretch"
              SelectedItem="{Binding SelectedOne, Mode=TwoWay}"
              IsSynchronizedWithCurrentItem="True">
</ListView>

模型视图:

ObservableCollection<ItemViewModel> _EAItems = new ObservableCollection<ItemViewModel>();
public ObservableObject _selectedOne;

public ObservableCollection<ItemViewModel> Items
        {
            get
            {
                return _EAItems;
            }
            set
            {
                _EAItems = value;
            }
        }

public ObservableObject SelectedOne 
        {
            get { return _selectedOne; }
            set 
            {

                if(_selectedOne != value)
                _selectedOne = value;

            }
        }
Select = new RelayCommand(() => 
            {
                if (qw == 15) { qw = 0; }else
                SelectedOne = Items[qw];
                qw++;
            });

项目是ObservableCollection

我添加了另一个 Listview 并将其绑定到相同的源。当我在 Listview 之一中更改 SelctedItem 时,它会显示在另一个 SelctedItem 上,反之亦然。

我查看了很多类似的解决方案,但我不知道出了什么问题:(

【问题讨论】:

  • 我找不到参考,但我相信当属性更改的源是 UI 时,会隐含属性更改事件 - 这就是为什么带有 2 个 ListViews 的示例正在工作的原因跨度>
  • 非常感谢大家,成功了

标签: c# wpf data-binding mvvm


【解决方案1】:

首先,您还应该发布 ItemsSource 的绑定代码,即 ItemsSource 属性。

但主要问题是您没有在 setter 中调用 PropertyChanged

    public ObservableObject SelectedOne 
    {
        get { return _selectedOne; }
        set 
        {

            if(_selectedOne != value)
            _selectedOne = value;

            OnPropertyChanged("SelectedOne ");//<-- otherwise the view dont know that the SelectedItem changed
        }
    }

【讨论】:

    【解决方案2】:

    为了使绑定工作,您必须从 SelectedOne 设置器中引发 PropertyChanged 事件。定义SelectedOne 属性的类必须实现INotifyPropertyChanged

    不管SelectedOne属性的类型是什么(即使它本身就是一个ObservableObject),当为属性发生变化。

    【讨论】:

    • SelectedObject 的类型是 ObservableObject,它已经继承了 PropertyChanged 和 PropertyChanging 接口。它在 MVVM-light 库中实现
    • 这不是重点。这里的属性是什么类型并不重要。 SelectedOne setter 必须引发 PropertyChanged 事件。请参阅@blindmeis 的答案中的示例代码。
    • 抱歉,我看不到两个 ListView。第二个在哪里?
    • @SergSolohin 请参阅我对原始问题的评论以解释 2 ListView 行为
    • 没有任何隐藏的魔法是行不通的。您要么没有发布所有相关代码,要么正在观察某种次要效应。将两个 ListView 的 SelectedItem 绑定到不触发 PropertyChanged 的​​属性(也不是依赖属性)不会使它们保持同步。
    【解决方案3】:

    我同意 Clemens 和blindmeis 的观点。唯一的事实是 SelectedOne 需要与为 Collection 设置的类相同。对于 MVVM-light 库,方法是 RaisePropertyChanged 而不是 OnPropertyChanged(如果您的 viewModel 继承自 ViewModelBase)。

    如果您的源代码包含 ItemViewModels 应使用此代码:

    private ItemViewModel _selectedOne;
    
    public ItemViewModel SelectedOne 
    {
        get { return _selectedOne; }
        set 
        {
    
            if(_selectedOne != value)
            _selectedOne = value;
    
            RaisePropertyChanged("SelectedOne");
        }
    }
    

    您的集合不需要 RaisePropertyChanged 的​​原因是 ObsvervableCollection 类已经以某种方式包含它。

    问候,

    凯文

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-08-19
      • 1970-01-01
      • 1970-01-01
      • 2023-01-19
      • 1970-01-01
      • 2020-05-27
      • 1970-01-01
      相关资源
      最近更新 更多