gpt4 book ai didi

c# - 绑定(bind) OneWayToSource - 奇怪的行为

转载 作者:行者123 更新时间:2023-11-30 15:32:35 27 4
gpt4 key购买 nike

我最近用 Binding Mode = OneWayToSource 做了很多测试,但我仍然不知道为什么会发生某些事情。

例如,我在类构造函数中为 dependency property 设置了一个值。现在,当 Binding 初始化时,Target 属性被设置为其默认值。意味着 dependency property 被设置为 null 并且我丢失了我在 constructor 中初始化的值。

为什么会这样? 绑定(bind)模式 并不像名称描述的那样工作。它应该只更新 Source 而不是 Target

代码如下:

public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new MyViewModel();
}

private void OnClick(object sender, RoutedEventArgs e)
{
this.DataContext = new MyViewModel();
}
}

这是 XAML:

<StackPanel>
<local:MyCustomControl Txt="{Binding Str, Mode=OneWayToSource}"/>
<Button Click="OnClick"/>
</StackPanel>

这是我的自定义控件:

    public class MyCustomControl : Control
{
public static readonly DependencyProperty TxtProperty =
DependencyProperty.Register("Txt", typeof(string), typeof(MyCustomControl), new UIPropertyMetadata(null));

static MyCustomControl()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(MyCustomControl), new FrameworkPropertyMetadata(typeof(MyCustomControl)));
}

public MyCustomControl()
{
this.Txt = "123";
}

public string Txt
{
get { return (string)this.GetValue(TxtProperty); }

set { this.SetValue(TxtProperty, value); }
}
}

这是 View 模型:

    public class MyViewModel : INotifyPropertyChanged
{
private string str;

public string Str
{
get { return this.str; }
set
{
if (this.str != value)
{
this.str = value; this.OnPropertyChanged("Str");
}
}
}

protected void OnPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null && propertyName != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}

public event PropertyChangedEventHandler PropertyChanged;
}

最佳答案

this.Txt = "123";

这是用本地值替换您的绑定(bind)。参见 dependency property value precedence .您实际上是在调用 DependencyObject.SetValue当你真的想要DependencyProperty.SetCurrentValue .此外,您需要等到生命周期后期才执行此操作,否则 WPF 将更新 Str 两次:一次使用“123”,然后再次使用 null:

protected override void OnInitialized(EventArgs e)
{
base.OnInitialized(e);
this.SetCurrentValue(TxtProperty, "123");
}

如果您在用户控件的构造函数中执行此操作,它会在 WPF 实例化它时执行,但会在 WPF 加载、反序列化和应用您的 BAML 时立即被替换。

更新:抱歉,我误解了你的确切问题,但现在有一个复制品,复制如下。我遗漏了您随后更新 DataContext 的部分。我通过在数据上下文更改时设置当前值来解决此问题,但在单独的消息中。否则,WPF 会忽略将更改转发到您的新数据源。

using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;

namespace SO18779291
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.setNewContext.Click += (s, e) => this.DataContext = new MyViewModel();
this.DataContext = new MyViewModel();
}
}

public class MyCustomControl : Control
{
public static readonly DependencyProperty TxtProperty =
DependencyProperty.Register("Txt", typeof(string), typeof(MyCustomControl), new UIPropertyMetadata(OnTxtChanged));

static MyCustomControl()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(MyCustomControl), new FrameworkPropertyMetadata(typeof(MyCustomControl)));
}

public MyCustomControl()
{
this.DataContextChanged += (s, e) =>
{
this.Dispatcher.BeginInvoke((Action)delegate
{
this.SetCurrentValue(TxtProperty, "123");
});
};
}

public string Txt
{
get { return (string)this.GetValue(TxtProperty); }

set { this.SetValue(TxtProperty, value); }
}

private static void OnTxtChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
Console.WriteLine("Changed: '{0}' -> '{1}'", e.OldValue, e.NewValue);
}
}

public class MyViewModel : INotifyPropertyChanged
{
private string str;

public string Str
{
get { return this.str; }
set
{
if (this.str != value)
{
this.str = value; this.OnPropertyChanged("Str");
}
}
}

protected void OnPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null && propertyName != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}

public event PropertyChangedEventHandler PropertyChanged;
}
}

XAML:

<Window x:Class="SO18779291.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SO18779291"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<local:MyCustomControl Txt="{Binding Str, Mode=OneWayToSource}"/>
<Button x:Name="setNewContext">New Context</Button>
<TextBlock Text="{Binding Str, Mode=OneWay}"/>
</StackPanel>
</Window>

关于c# - 绑定(bind) OneWayToSource - 奇怪的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18779291/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com