XAML 属性 更改时数据绑定未更新 UI
XAML Data Binding not updating UI when property changes
当整数字段更改时,我无法获取要更新的简单数据绑定标签。我已经实施了 INotifyPropertChanged,当我更改变量值时会触发此事件。 UI 不会更新,标签也不会更改。我过去没有做过太多数据绑定,所以我可能遗漏了一些东西,但我还没有找到它。
这是我的 XAML:
<Window x:Class="TestBinding.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:TestBinding"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<Button Command="{Binding TestCommand, Mode=OneWay}" >
<Button.DataContext>
<local:TestVM/>
</Button.DataContext> Add 1</Button>
<Label Content="{Binding Count,
Mode=OneWay,UpdateSourceTrigger=PropertyChanged}">
<Label.DataContext>
<local:TestVM/>
</Label.DataContext>
</Label>
</StackPanel>
</Window>
这是我的 C# 视图模型:
class TestVM : INotifyPropertyChanged
{
private int _count;
private RelayCommand _testCommand;
public TestVM ()
{
Count=0;
}
public int Count
{
get { return _count; }
set { _count = value; OnPropertyChanged(); }
}
public void Test()
{
Count++;
}
public ICommand TestCommand
{
get
{
if (_testCommand == null)
{
_testCommand = new RelayCommand(param => this.Test(), param => true);
}
return _testCommand;
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = "")
{
if (this.PropertyChanged != null)
{
Console.WriteLine(propertyName);
var e = new PropertyChangedEventArgs(propertyName);
this.PropertyChanged(this, e);
}
}
}
这是我的 ICommand C#(以防您需要它来复制我所拥有的):
public class RelayCommand : ICommand
{
#region Fields
readonly Action<object> _execute;
readonly Predicate<object> _canExecute;
#endregion // Fields
#region Constructors
public RelayCommand(Action<object> execute) : this(execute, null) { }
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null) throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
#endregion // Constructors
#region ICommand Members [DebuggerStepThrough]
public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter)
{
_execute(parameter);
}
#endregion
// ICommand Members
}
非常感谢任何帮助。
编辑:
我将 xaml 更新为 toadflakz 建议的内容并且有效。
<Window x:Class="TestBinding.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:TestBinding"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:TestVM/>
</Window.DataContext>
<StackPanel>
<Button Command="{Binding TestCommand, Mode=OneWay}" >Add 1</Button>
<Label Content="{Binding Count, Mode=OneWay,UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>
</Window>
您的问题与将 DataContext 绑定到各个控件的方式有关。您的 ViewModel 不会自动成为单例(仅限单个实例的对象),因此每次指定它时,您实际上是在创建一个单独的实例。
如果您将 DataContext 设置为 Window 级别,您的代码应该会按预期工作。
将 Window
的 DataContext
设置为:
<Window......
<Window.DataContext>
<local:TestVM/>
</Window.DataContext>
</Window>
You have set the DataContext
for Button
and Label
separately, so there will be two different objects of TestVM
class
. Command
will be executed in first and change values in it,
while your Label
display the values from another object.
当整数字段更改时,我无法获取要更新的简单数据绑定标签。我已经实施了 INotifyPropertChanged,当我更改变量值时会触发此事件。 UI 不会更新,标签也不会更改。我过去没有做过太多数据绑定,所以我可能遗漏了一些东西,但我还没有找到它。
这是我的 XAML:
<Window x:Class="TestBinding.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:TestBinding"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<Button Command="{Binding TestCommand, Mode=OneWay}" >
<Button.DataContext>
<local:TestVM/>
</Button.DataContext> Add 1</Button>
<Label Content="{Binding Count,
Mode=OneWay,UpdateSourceTrigger=PropertyChanged}">
<Label.DataContext>
<local:TestVM/>
</Label.DataContext>
</Label>
</StackPanel>
</Window>
这是我的 C# 视图模型:
class TestVM : INotifyPropertyChanged
{
private int _count;
private RelayCommand _testCommand;
public TestVM ()
{
Count=0;
}
public int Count
{
get { return _count; }
set { _count = value; OnPropertyChanged(); }
}
public void Test()
{
Count++;
}
public ICommand TestCommand
{
get
{
if (_testCommand == null)
{
_testCommand = new RelayCommand(param => this.Test(), param => true);
}
return _testCommand;
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = "")
{
if (this.PropertyChanged != null)
{
Console.WriteLine(propertyName);
var e = new PropertyChangedEventArgs(propertyName);
this.PropertyChanged(this, e);
}
}
}
这是我的 ICommand C#(以防您需要它来复制我所拥有的):
public class RelayCommand : ICommand
{
#region Fields
readonly Action<object> _execute;
readonly Predicate<object> _canExecute;
#endregion // Fields
#region Constructors
public RelayCommand(Action<object> execute) : this(execute, null) { }
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null) throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
#endregion // Constructors
#region ICommand Members [DebuggerStepThrough]
public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter)
{
_execute(parameter);
}
#endregion
// ICommand Members
}
非常感谢任何帮助。
编辑: 我将 xaml 更新为 toadflakz 建议的内容并且有效。
<Window x:Class="TestBinding.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:TestBinding"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:TestVM/>
</Window.DataContext>
<StackPanel>
<Button Command="{Binding TestCommand, Mode=OneWay}" >Add 1</Button>
<Label Content="{Binding Count, Mode=OneWay,UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>
</Window>
您的问题与将 DataContext 绑定到各个控件的方式有关。您的 ViewModel 不会自动成为单例(仅限单个实例的对象),因此每次指定它时,您实际上是在创建一个单独的实例。
如果您将 DataContext 设置为 Window 级别,您的代码应该会按预期工作。
将 Window
的 DataContext
设置为:
<Window......
<Window.DataContext>
<local:TestVM/>
</Window.DataContext>
</Window>
You have set the
DataContext
forButton
andLabel
separately, so there will be two different objects ofTestVM
class
.Command
will be executed in first and change values in it, while yourLabel
display the values from another object.