我刚刚开始使用 WPF,但仍然没有清楚地了解它的所有事实。
现在我正在搞乱数据绑定和线程来更新数据并按时间表示它。我有一个带有 2 个文本框的主窗口和一个用一个线程定义的用户控件,当我单击它时该线程开始运行。在这个线程中,我调用了在我绑定到文本框的主窗口中设置的 2 个属性,一个通过代码,另一个通过 xaml。
问题是代码生成的数据绑定有效,而 xaml 生成的数据绑定仅在我直接更新文本框时才有效。我一直想知道为什么,并通过一些更改使其工作,但我怀疑这个解决方案是“正确的”。
代码是这样的
主窗口.xaml
<Window x:Class="WpfApplication1.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" Loaded="Window_Loaded" xmlns:my="clr-namespace:WpfApplication1.Elements">
<Grid>
<TextBox Name="Textbox1" Height="23" HorizontalAlignment="Left" Margin="188,50,0,0" VerticalAlignment="Top" Width="120" Background="White" Text="{Binding Source=my:MainWindow, Path=datavalue}" />
<TextBox Name="textBox2" Background="White" Height="23" HorizontalAlignment="Left" Margin="188,101,0,0" Text="{Binding Path=datavalue2, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}} }" VerticalAlignment="Top" Width="120" />
<Label Content="Label" Height="28" HorizontalAlignment="Left" Margin="202,152,0,0" Name="label1" VerticalAlignment="Top" />
<my:Test Margin="81,138,346,92" x:Name="test1" />
</Grid>
</Window>
主窗口.xaml.cs
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window, INotifyPropertyChanged
{
public MainWindow()
{
InitializeComponent();
}
public event PropertyChangedEventHandler PropertyChanged;
private int MydataValue;
public int datavalue
{
get
{
return MydataValue;
}
set
{
MydataValue = value;
if (PropertyChanged != null)
{
PropertyChanged(this,
new PropertyChangedEventArgs(
"datavalue"));
}
}
}
private int mydatavalue2;
public int datavalue2
{
get
{
return mydatavalue2;
}
set{
mydatavalue2 = value;
}
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
datavalue2 = 10;
datavalue = 15;
Binding bind = new Binding();
bind.Source = this;
bind.Mode = BindingMode.TwoWay;
bind.Path = new PropertyPath("datavalue");
Textbox1.SetBinding(TextBox.TextProperty, bind);
}
}
}
这是用户控件
测试.xaml.cs
namespace WpfApplication1.Elements
{
/// <summary>
/// Interaction logic for Test.xaml
/// </summary>
public partial class Test : UserControl
{
private Thread t;
private int resolution;
private Stopwatch sw,sw2;
private delegate void changeIconDelegate(long ib);
private ImageBrush b;
private Boolean end=false;
private int count = 0;
public Test()
{
InitializeComponent();
sw = new Stopwatch();
sw2 = new Stopwatch();
b = new ImageBrush();
resolution = 100;
}
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
b.ImageSource = new BitmapImage(new Uri("pack://application:,,,/DataBinding;component/Images/249137482.png", UriKind.Absolute));
this.Background = b;
}
private void UserControl_MouseUp(object sender, MouseButtonEventArgs e)
{
t = new Thread(new ThreadStart(ThreadTask));
t.Start();
}
private void ThreadTask()
{
while (!end)
{
count = count + 1;
Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action)delegate()
{
Application.Current.Windows.OfType<MainWindow>().First().datavalue = count;
Application.Current.Windows.OfType<MainWindow>().First().datavalue2 = count;
});
Thread.Sleep((resolution - sw.Elapsed.TotalMilliseconds) > 0 ? TimeSpan.FromMilliseconds(resolution - sw.Elapsed.TotalMilliseconds):TimeSpan.FromMilliseconds(1));
sw.Reset();
sw.Start();
}
}
}
}
如果我启动应用程序,只要我单击控件,textbox1 就会开始更新,而 textbox2 不会,但是如果我直接更改 textbox2,它会抛出它已更改的通知,因此数据绑定正常或我认为.
问题是:
如果直接修改而不是在用户控件的线程中调用,为什么它会起作用?我认为它与 xaml 文件中 textbox2 的声明有关,因为它搜索祖先,而 usercontrol 是一个孩子,但我不知道如何处理这个问题。
propertychanged 事件适用于类的每个属性,但是如果执行多线程处理,它可能会采用不正确的值并将一个事件误认为另一个事件?
我确定我没有正确使用 WPF 的规范,也许这会以某种方式影响代码,例如从用户控件调用 mainwindow 时:S
对于大量的代码和问题,我很抱歉,但我开始喜欢 WPF,当我没有让事情正常工作时,我感到有些沮丧。我搜索了类似的问题,但只发现人们在必须从主 UI 更新控件属性时遇到问题,而不是像我这样的其他方式