【发布时间】: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,以通过解决通常的绑定问题无法解决的方式重现他们的问题(我怀疑他们能够做到,但如果他们可以的话,他们将拥有更多权力)。