【发布时间】:2016-09-23 15:34:24
【问题描述】:
即使在查看了大量解决方案建议之后,我也无法在 xaml 中使用简单的双向绑定。我有一个窗口、一个 dataContext 和一个应用程序。问题是:
a) 当 App 构造函数运行时,窗口(在同一个构造函数中初始化和.Show-ed)出现,但根本没有更新,即使我在 C# 代码中切换了复选框值几次;
b) 当 App 构造函数完成时,Window 只更新一次;我已经设置好了,如果我单击窗口中的复选框,App 中的事件处理程序(绑定到 DataContext 属性更改通知)应该会增加字符串列表的大小,该列表也会显示出来。列表的增加在代码中正确发生,但没有反映在 Window 中。
总结:
- Window 中的用户输入可以很好地到达应用程序的 C# 代码:我可以对复选框更改等进行操作。
- 相反的方向不起作用:每当通过代码更改 dataContext 中的项目时,即使实现并执行了 iNotifyProperty,窗口也不会自动更新。
我所期望的是:
a) 当 App 构造函数运行并切换 CheckBox 值时,窗口应通过设置/清除框上的勾号来反映更改;
b) 在 App 构造函数完成后,每当我将 CheckBox 从 FALSE 切换为 TRUE 时,NameList 都会附加一个新字符串。我希望 Window 中的列表会相应增加并自动显示完整的、附加的 NameList 内容。
观察:
- 我尝试确保在Window 上调用
InitializeComponent之前设置了Window 上的DataContext。不幸的是,并没有真正的不同... -
我在 VS 中的 MainWindow.xaml 文件中得到了一条线索:CheckBox Path 和 ListBox Binding
NameList被注释为Cannot resolve symbol due to unknown DataContext但是,当 App 构造函数终止时,Window 会更新并且当我单击 CheckBox 时,会触发正确的 NotifyProperty 事件。这告诉我,运行时绑定实际上应该可以工作......显然只有一种方式,而不是两种方式。
MainWindow.xaml:
<Window x:Class="StatisticsEvaluation.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<StackPanel Orientation="Vertical">
<CheckBox IsChecked="{Binding Path=IsChecked, Mode=TwoWay}" Content="CheckBox" />
<ListBox ItemsSource="{Binding NameList, Mode=TwoWay}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<TextBlock FontSize="18" FontFamily="Arial" Foreground="Black" Text="TextBlock" Visibility="Visible" />
</StackPanel>
</Grid>
MainWindow.xaml.cs:
namespace StatisticsEvaluation
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
}
}
}
App 和 DataContext:
namespace StatisticsEvaluation
{
public class DataContextClass : INotifyPropertyChanged
{
private bool isChecked;
public bool IsChecked
{
get
{
return isChecked;
}
set
{
isChecked = value;
OnPropertyChanged("IsChecked");
}
}
private List<string> nameList;
public List<string> NameList
{
get
{
return nameList;
}
set
{
nameList = value;
OnPropertyChanged("NameList");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
private MainWindow MyWindow { get; set; }
private DataContextClass MyDataContext{ get; set; }
private void HandleDataContextPropertyChange(object sender, PropertyChangedEventArgs e)
{
// If the CheckBox was just toggled to TRUE, increase the NameList
// with an additional name and call OnPropertyChanged on it ...
// hoping that this would trigger a Window UI update - but no luck !
if ((e.PropertyName == "IsChecked") && MyDataContext.IsChecked)
{
var randomProvider = new Random();
MyDataContext.NameList.Add(randomProvider.Next().ToString());
MyDataContext.OnPropertyChanged("NameList");
}
}
public App()
{
MyDataContext = new DataContextClass();
MyDataContext.PropertyChanged += HandleDataContextPropertyChange;
MyWindow = new MainWindow {DataContext = MyDataContext};
MyWindow.InitializeComponent();
MyWindow.Show();
MyDataContext.NameList = new List<string>();
MyDataContext.NameList.Add("FirstName");
MyDataContext.NameList.Add("SecondName");
MyDataContext.NameList.Add("ThirdName");
MyDataContext.IsChecked = true;
Thread.Sleep(3000);
MyDataContext.IsChecked = false;
Thread.Sleep(3000);
MyDataContext.IsChecked = true;
}
}
}
当我启动应用程序时,一旦应用程序构造函数点击.Show,就会出现以下窗口:
一旦 App 构造器完成,Window 会更新一次,但以后不会再更新,无论有多少字符串添加到 NameList:
任何想法,为什么我的双向绑定只能在一个方向上工作?
【问题讨论】:
-
我建议你删除
App中所有奇怪的MyDataContext东西,然后在 MainWindow 构造函数或其他东西中创建视图模型。此外,对于将绑定到 WPF 中的控件的集合,请始终使用ObservableCollection<T>。不要使用列表。当其内容发生变化时,它不会引发事件。 -
ItemsSource="{Binding NameList, Mode=TwoWay}"没有意义。 ItemsControl 永远不会更改其ItemsSource属性,因此设置Mode=TwoWay永远不会有任何效果。除此之外,MyDataContext.OnPropertyChanged("NameList");被静默忽略,因为 NameList 实例没有改变。所以使用 ObservableCollection。 -
先生们-谢谢!事实上,我的主要错误是不使用 ObservableCollection。我还删除了 NameList 绑定上的“Mode=TwoWay”,并且 - 正如您提到的,Clemens - 它确实没有任何效果(并且在没有明确设置 TwoWay 模式的情况下完美地工作)。感谢您指出了这一点。 Ed,我将尝试在 MainWindow 中创建视图模型。我现在的代码更像是对我自己的可行性检查。那(以及我有限的 WPF 知识)导致了不寻常的结构。我会改正的。