哦,主啊,又是星期一了,我觉得我所有关于wpf的知识都被删除了。
我认为在模式PropertyChanged中绑定时,源将只在目标属性被更改时才会更新,而不是一直更新。
下面是一个例子,在这个例子中,尽管Target属性没有被更改,绑定仍然在不断地更新Source。为什么?
顺便说一句,我在.NET 4.0
<StackPanel>
<TextBox x:Name="tbx1" Text="{Binding Txt, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<Button Content="Change Text" Click="OnClick" />
</StackPanel>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new ViewModel();
}
private void OnClick(object sender, RoutedEventArgs e)
{
tbx1.Text = "hello";
}
}
public class ViewModel
{
private string txt;
public string Txt
{
get { return txt; }
set { txt = value; Console.WriteLine("Txt Setter Called!");}
}
}每当我点击Button,Txt的设置程序就会被调用。为什么?值未被更改。
GetHashCode()方法返回相同的结果。
我少了什么??:-)
发布于 2014-02-10 17:47:52
正如您所预期的,没有发生实际的“属性更改”,可以通过以下方法确认:
using System.ComponentModel;
var descriptor = DependencyPropertyDescriptor.FromProperty(TextBox.TextProperty, typeof(TextBox));
descriptor.AddValueChanged(tbx1, (s, e) => Console.WriteLine("tbx1 changed"));“已更改的tbx1”只出现一次。
如果源是一个依赖项属性,那么它也不会改变。尝试添加另一个文本框并将其用作源代码,而不是视图模型:
<TextBox Name="tbx2" />
<TextBox Name="tbx1" Text="{Binding ElementName=tbx2, Path=Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />处理程序:
descriptor.AddValueChanged(tbx2, (s, e) => Console.WriteLine("tbx2 changed"));再说一次,只有一次改变。
所以是的,扳机没有准确的命名。此行为的一个原因可能是确保属性集总是触发绑定转换器,因为即使输入相同,ConvertBack也可以返回不同的值。
无论如何,目标和源都需要承担一定的责任来确定“更改”是什么。毕竟,如果这是一个真正的双向绑定,那么应该允许我们以完全相同的效果以这种方式实现OnClick:
tbx1.DataContext.Txt = "hello";因此,只需确保属性设置者在继续之前始终检查实际更改(就像依赖项属性一样)。
发布于 2014-02-10 09:58:30
好吧,这就是它的工作方式,但这个名字可能有点误导。
在设置目标属性时更新源值,而不一定是在值更改时(如名称所示)。
您可以通过使用fx观察相同的行为。一个CheckBox。一次又一次地将IsChecked属性设置为true也会触发源更新,即使目标值没有变化。
因此,绑定系统在触发更新之前不对实际值进行比较,它只关心目标属性是否已设置。
用CheckBox扩展了您的示例
XAML:
<StackPanel>
<TextBox x:Name="tbx1" Text="{Binding Txt, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<CheckBox x:Name="chk1" IsChecked="{Binding IsChecked, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<Button Content="Change Text" Click="OnClick" />
</StackPanel>代码隐藏:
public partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new ViewModel();
}
private void OnClick(object sender, RoutedEventArgs e)
{
tbx1.Text = "hello";
chk1.IsChecked = true;
}
}
public class ViewModel
{
private string txt;
public string Txt
{
get { return txt; }
set { txt = value; Console.WriteLine("Txt Setter Called!"); }
}
private bool isChecked;
public bool IsChecked
{
get { return isChecked; }
set { isChecked = value; Console.WriteLine("IsChecked Setter Called!"); }
}
}发布于 2014-02-10 07:59:56
将BindingMode更改为OneWay或OneWayToSource。你的问题会解决的..。
<TextBox x:Name="tbx1" Text="{Binding Txt, Mode=OneWayToSource, UpdateSourceTrigger=PropertyChanged}"/>https://stackoverflow.com/questions/21671727
复制相似问题