【问题标题】:INotifyPropertyChanged binding selected checkboxes in MVVM [duplicate]INotifyPropertyChanged 在 MVVM 中绑定选中的复选框 [重复]
【发布时间】:2018-02-04 20:53:18
【问题描述】:

我正在尝试将我的 CheckBoxList 从代码隐藏重写为 WPF C# 中的 MVVM 模式。问题是现在我在获取所有选中的复选框时遇到了问题。我已经实现了 INotifyPropertyChanged 接口。项目正在正确构建,当我设置断点时,我可以注意到我的复选框始终收到错误值,即使它们被选中。我认为也许我在数据绑定方面做错了。请问,有人可以帮忙吗?我是 MVVM 的新手。

INotifyPropertyChanged 实现

    public class ObservableObject : INotifyPropertyChanged
    {

        #region INotifyPropertyChanged

        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string strPropertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(strPropertyName));
        }

        #endregion

    }
}

型号

 public class SharedModel : ObservableObject
    {

        public bool IsSelected { get; set; }

        public string Name { get; set; }

        public string Method { get; set; }
    }

视图模型

   class TestViewModel : ObservableObject
    {
                private bool _fIsSelected;

                public bool IsSelected
                {
                    get => _fIsSelected;
                    set
                    {
                        _fIsSelected = value;
                        OnPropertyChanged("IsSelected");
                    }
                }

        public ObservableCollection<SharedModel> List { get; set; } = new ObservableCollection<SharedModel>
        {
            new SharedModel
            {
                Name = "A1",
                Method = Test(),
            },
            new SharedModel
            {
                Name = "A2",
                Method = TestOne()
            }
};

        public string GetSelectedCheckboxes()
        {
             var command =
                    from item in List
                    where item.IsSelected
                    select item.Method;
          return string.Join("\r&", new NewList<string>(command).ToArray());
        }

XAML 中的复选框列表

<StackPanel Margin="0,0,769,510">
            <ListBox Name="ListBox"
                     ScrollViewer.HorizontalScrollBarVisibility="Disabled"
                     ItemsSource="{Binding List}"
                     SelectionMode="Multiple" Background="{x:Null}" Margin="0,133,590,470" Foreground="White" BorderBrush="{x:Null}">
                <ListBox.ItemsPanel>
                    <ItemsPanelTemplate>
                        <WrapPanel />
                    </ItemsPanelTemplate>
                </ListBox.ItemsPanel>
                <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal"
                                    MinWidth="170" MaxWidth="170"
                                    Margin="0,0, 0, 0" >
                            <CheckBox x:Name="TestCheckbox"
                                      Tag="{Binding Method}" IsChecked="{Binding IsSelected}" />
                            <ContentPresenter
                                Content="{Binding Name}"
                                Margin="5,0, 15, 0" />
                        </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
        </StackPanel>

测试视图

public partial class TestView : UserControl
{

    public TestView()
    {
        InitializeComponent();
        DataContext = new TestViewModel();
    }

【问题讨论】:

  • SharedModel 继承 ObservableObject,但并不费心实际调用 OnPropertyChanged() 方法。因此从未观察​​到对IsSelected 的更改。有关正确实现INotifyPropertyChanged的基础知识,请参阅标记的副本。
  • @PeterDuniho 虽然你说的完全正确,但我认为这不是这里的实际问题。如果我理解正确,来自 UI 的更改不会按预期反映在 ViewModel 中,而不是相反。并且 UI 更改应该反映在 ViewModel 中,即使 setter 中没有 OnPropertyChanged(),对吧?实际上,使用发布的代码(带有一些更正的括号),我看到 UI 更改反映在使用 Snoop 的TestViewModel 中。所以错误一定在其他地方,我猜......
  • @MaSiMan:我同意上面的代码有效。所以,我想这个问题可能不会因为缺少minimal reproducible example 而关闭。但是,绑定不是火箭科学。它总是归结为:实现属性更改通知,并确保数据上下文符合您的期望。标记的副本确实解决了这个问题。如果 OP 感觉不同,他们可以编辑问题以提供minimal reproducible example,以通过解决通常的绑定问题无法解决的方式重现他们的问题(我怀疑他们能够做到,但如果他们可以的话,他们将拥有更多权力)。

标签: c# wpf xaml mvvm


【解决方案1】:

绑定集合时,需要3种Change Notification:

  • 从集合中添加或删除元素时的通知。这是 唯一 ObservableCollection&lt;T&gt; 负责的事情
  • 关于公开集合的属性的更改通知。用新的实例替换整个集合通常是必要的。这将是您代码中的属性“列表”,但从技术上讲,不应该编译,因为列表是一个非常常见的类。
  • 您在该集合中持有的 T 类型的每个属性的更改通知。在您的情况下,这将是 SharedModel。

你的缩进有点乱,所以我在解析你发布的代码时遇到了一些问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-09-01
    • 1970-01-01
    • 2018-06-08
    • 2016-10-21
    • 1970-01-01
    • 1970-01-01
    • 2020-06-27
    • 1970-01-01
    相关资源
    最近更新 更多