我是WPF的新手,我正在尝试做我认为简单的任务 - 在我的业务对象中显示字段的值,因为它在我的程序中发生了变化。我知道如何通过手动更改C#中的TextBox.Text属性来“强制”更改它,但是当我正在学习WPF时,我想以“正确”的方式进行,这意味着数据绑定。
问题#1:据我了解,我的选择是使用DependencyProperty还是在我的业务对象中实现INotifyPropertyChanged,对吧?
问题2:这是我的代码的通用版本,我试图在其中使用DependencyProperty路由。
标记:
Button x:Name="nextButton" Content="Click" Grid.Row="2" Click="nextButton_Click" />
TextBox x:Name="myTextBox" Grid.Row="1" Text="{Binding Source=myTest, Path=Name, UpdateSourceTrigger=PropertyChanged, NotifyOnSourceUpdated=True}"/>
代码隐藏:
namespace DependencyTest2
{
///
/// Interaction logic for MainWindow.xaml
///
public partial class MainWindow : Window
{
private int i;
private TestSphere myTest;
public MainWindow()
{
InitializeComponent();
i = 0;
myTest = new TestSphere();
}
private void nextButton_Click(object sender, RoutedEventArgs e)
{
switch (i)
{
case 0:
myTest.Name = "string1";
break;
case 1:
myTest.Name = "string2";
break;
case 2:
myTest.Name = "string3";
break;
}
i++;
}
}
class TestSphere : DependencyObject
{
public string Name
{
get { return (string)GetValue(NameProperty); }
set { SetValue(NameProperty, value); }
}
public static readonly DependencyProperty NameProperty =
DependencyProperty.Register("Name", typeof(string), typeof(TestSphere));
public TestSphere()
{
Name = "default";
}
}
}
当我运行程序时,文本框中没有任何内容,即使绑定属性有值 - 我还需要做些什么来提醒绑定源值已经改变了吗?我认为使用DependencyProperty作为源代码可以解决这个问题,但话说回来,我是WPF的新秀。谢谢!
好的,我尝试使用我在codeproject上找到的包装器类实现INotifyPropertyChanged,如下所示:
class TestSphere : NotifyProperyChangedBase
{
private string _Name;
public string Name
{
get { return _Name; }
set
{
this.CheckPropertyChanged("Name", ref _Name, ref value);
}
}
public TestSphere()
{
Name = "default";
}
}
public abstract class NotifyProperyChangedBase : INotifyPropertyChanged
{
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
#region methods
protected bool CheckPropertyChanged(string propertyName, ref T oldValue, ref T newValue)
{
if (oldValue == null && newValue == null)
{
return false;
}
if ((oldValue == null && newValue != null) || !oldValue.Equals((T)newValue))
{
oldValue = newValue;
FirePropertyChanged(propertyName);
return true;
}
return false;
}
protected void FirePropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
这也是我的新Markup:
Grid Name="myGrid">
Grid.RowDefinitions>
RowDefinition Height="30"/>
RowDefinition Height="30"/>
RowDefinition Height="30"/>
RowDefinition Height="*"/>
/Grid.RowDefinitions>
Label x:Name="myLabel" Grid.Row="0" Foreground="Black" />
Button x:Name="nextButton" Content="Click" Grid.Row="2" Click="nextButton_Click" />
TextBox x:Name="myTextBox" Grid.Row="1" Text="{Binding Path=myTest.Name}"/>
/Grid>
我在实例化myTest后立即将行myGrid.DataContext = myTest;
添加到'public MainWindow()'。当我逐步执行生成的程序时,this.PropertyChanged
的值总是计算为null
,因此PropertyChanged甚至不会触发。提前抱歉,这是一个非常棒的问题。
答案 0 :(得分:1)
您应该只需要在TestSphere类上实现INotifyPropertyChanged
,而不是在DependencyObject上实现。在更新值时,请致电PropertyChanged(this, new PropertyChangedEventArgs("Name"))
。
其次,您需要在代码隐藏中为窗口设置DataContext。假设您在XAML中将此用作根网格元素:
<Grid Name="MainForm">
然后在你的代码隐藏中,你会这样做:
MainForm.DataContext = this;
最后,将myTest属性更改为public
,然后XAML中的绑定只需要
Text="{Binding Path=myTest.Name}"