Wpf 如果其他类对象的属性更改,Gui不更新
我想将自定义类(Wpf 如果其他类对象的属性更改,Gui不更新,wpf,xaml,data-binding,Wpf,Xaml,Data Binding,我想将自定义类(FooClass)的一些属性(FooClass.FooString)绑定到我的主窗口。下面(工作已知行为)是将某些数据绑定到gui的默认工作解决方案 我想做的是在第二个代码块中(不工作,但需要的行为)。将另一个类对象的一些属性公开到gui并更新它。 **问题**:TestString未得到更新(在gui上,代码隐藏起作用)。属性更改事件也是null`(未订阅?!) 这是绑定数据的错误方法吗 如果我将完整的Foo类对象绑定到gui,并将路径(属于文本块)设置为Foo.FooStri
FooClass
)的一些属性(FooClass.FooString
)绑定到我的主窗口。下面(工作已知行为)是将某些数据绑定到gui的默认工作解决方案
我想做的是在第二个代码块中(不工作,但需要的行为)。将另一个类
对象的一些属性
公开到gui并更新它。
**问题**:
TestString未得到更新(在gui上,代码隐藏起作用)。属性更改
事件也是
null`(未订阅?!)
这是绑定数据的错误方法吗
如果我将完整的Foo类
对象
绑定到gui,并将路径
(属于文本块
)设置为Foo.FooString
,gui和字符串
将更新。但我不想这样做
这就是解决问题的方法吗
工作已知行为
我可能还没有完全理解您想要什么,但这里有一个数据绑定的工作示例,它与您的示例有些接近
两个主要变化是:
将datacontext设置为VM,而不是代码隐藏
实际上,为OnPropertyChanged提供正确触发刷新所需的参数,即属性的名称
结果:
main window.xaml
<Window x:Class="ListViewColor.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<TextBlock Text="{Binding Foo.FooString}" VerticalAlignment="Center" HorizontalAlignment="Center" Background="Aqua"/>
</Grid>
</Window>
FooClass.cs
我希望这有帮助 是的,您是正确的,您需要通过“工作已知行为”部分进行绑定。您需要订阅INotifyPropertyChanged.PropertyChanged事件,然后从MainWindow类内部引发相同的事件。与其将this
akaMainWindow
类绑定到DataContext
,不如将Foo
绑定到DataContext
?然后可以将TextBlock
的Text
设置为绑定到FooString
。这让生活变得更轻松。@Bijington看一看解决方案1。你是那个意思吗?@kurakura88在我的应用程序中,我有不止一个不同的类对象,而不仅仅是一个。请注意,在主窗口中实现INotifyPropertyChanged是毫无意义的。没有应该触发更改通知的属性。@是的,这就是我的意思。不过,我不推荐这种方法,因为它与推荐的做法背道而驰。你真的应该坚持你原来的方法,我只是指出这在技术上是可能的。谢谢你的回复。1.实际上,它正在使用DataContext=this
。然后你必须定义你的路径,比如path=Foo.FooString
。2.看看@Dominicjons嘿,你两次都是对的!我学到了一些东西。但是我不明白这个问题,因为即使有这些变化,它也能完美地工作!除了上面编辑的代码,您还需要什么吗?
<Window x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance local:MainWindow}"
Title="MainWindow" Height="450" Width="800">
<Grid>
<TextBlock Text="{Binding Path=Foo.FooString}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Grid>
</Window>
public partial class MainWindow : Window
{
public string TestString => _Foo.FooString;
private readonly FooClass _Foo;
public MainWindow()
{
_Foo = new FooClass();
DataContext = this;
InitializeComponent();
Loaded += _OnLoaded;
}
private async void _OnLoaded(object sender, RoutedEventArgs e)
{
await Task.Delay(1000);
_Foo.ChangeTheProperty();
}
}
public class FooClass : INotifyPropertyChanged
{
public string FooString
{
get => _FooString;
set
{
if (_FooString == value) return;
_FooString = value;
OnPropertyChanged();
}
}
private string _FooString = "empty";
public void ChangeTheProperty()
{
FooString = "Loaded";
}
// ##############################################################################################################################
// PropertyChanged
// ##############################################################################################################################
#region PropertyChanged
/// <summary>
/// The PropertyChanged Eventhandler
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Raise/invoke the propertyChanged event!
/// </summary>
/// <param name="propertyName"></param>
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
<Window x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance local:MainWindow}"
Title="MainWindow" Height="450" Width="800">
<Grid>
<TextBlock Text="{Binding Path=TestString}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Grid>
</Window>
public partial class MainWindow : Window, INotifyPropertyChanged
{
public FooClass Foo { get; } = new FooClass();
public MainWindow()
{
Foo.PropertyChanged += (sender, args) => OnPropertyChanged(args.PropertyName);
DataContext = this;
InitializeComponent();
Loaded += _OnLoaded;
}
private async void _OnLoaded(object sender, RoutedEventArgs e)
{
await Task.Delay(1000);
Foo.ChangeTheProperty();
}
// ##############################################################################################################################
// PropertyChanged
// ##############################################################################################################################
#region PropertyChanged
/// <summary>
/// The PropertyChanged Eventhandler
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Raise/invoke the propertyChanged event!
/// </summary>
/// <param name="propertyName"></param>
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
<Window x:Class="ListViewColor.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<TextBlock Text="{Binding Foo.FooString}" VerticalAlignment="Center" HorizontalAlignment="Center" Background="Aqua"/>
</Grid>
</Window>
namespace ListViewColor
{
public partial class MainWindow : Window
{
public FooClass Foo { get; } = new FooClass();
public MainWindow()
{
DataContext = this;
InitializeComponent();
Loaded += _OnLoaded;
}
private async void _OnLoaded(object sender, RoutedEventArgs e)
{
await Task.Delay(1000);
Foo.ChangeTheProperty();
}
}
}
using System.ComponentModel;
using System.Runtime.CompilerServices;
public class FooClass : INotifyPropertyChanged
{
private string _FooString = "Empty";
public string FooString
{
get
{
return _FooString;
}
set
{
if (_FooString == value) return;
_FooString = value;
OnPropertyChanged();
}
}
public void ChangeTheProperty()
{
FooString = "Loaded";
}
#region PropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}