WPF:如何在绑定值更改时编辑标签?
WPF: how do I edit a label when bound values change?
我正在尝试在 WPF 中创建一个用户控件(使用 xceed)。我有一个组合框和一个 integerUpDown。
标签应在其中一个更改其值时更改其内容。第一个标签只有一个简单的绑定到 integerUpDown,这是有效的。 Visual Studio 自动创建了 OnPropertyChanged()
和 getters/setters,我尝试使用它将我的结果绑定到第二个标签,但它不起作用。没有任何反应。
这是我的 XAML:
<UserControl x:Class="WpfApp2.CardSelectionControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfApp2" xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<StackPanel Margin="5" Width="300" Height="400" Background="LightGray">
<TextBox Margin="5" AcceptsReturn="True" FontSize="20" Padding="5" Height="70">placeholding</TextBox>
<ComboBox SelectedIndex="{Binding SelectedIndex}" Background="Red" Margin="5">
<ComboBoxItem Content="card1"></ComboBoxItem>
<ComboBoxItem Content="card2"></ComboBoxItem>
</ComboBox>
<xctk:UIntegerUpDown Margin="5" x:Name="upDown" Value="{Binding Level}" ></xctk:UIntegerUpDown>
<Label Height="50" Content="{Binding Level}"></Label>
<Label Height="50" Content="{Binding Result}" ></Label>
</StackPanel>
</UserControl>
后面的代码:
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;
namespace WpfApp2
{
public partial class CardSelectionControl : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public int Level
{
get { OnPropertyChanged(); return (int)GetValue(LevelProperty); }
set
{
OnPropertyChanged();
SetValue(LevelProperty, value);
}
}
public int SelectedIndex
{
get { OnPropertyChanged(); return (int)GetValue(SelectedIndexProperty); }
set
{
OnPropertyChanged();
SetValue(SelectedIndexProperty, value);
}
}
public int Result
{
get { return (int)GetValue(ResultProperty); }
set { SetValue(ResultProperty, value); }
}
protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
if (SelectedIndex == 0)
{ Result = Level * 2; }
else if (SelectedIndex == 1)
{ Result = Level * 3; }
}
public static readonly DependencyProperty ResultProperty =
DependencyProperty.Register("Result", typeof(int), typeof(CardSelectionControl), new PropertyMetadata(20));
public static readonly DependencyProperty LevelProperty =
DependencyProperty.Register("Level", typeof(int), typeof(CardSelectionControl), new PropertyMetadata(10));
public static readonly DependencyProperty SelectedIndexProperty =
DependencyProperty.Register("SelectedIndex", typeof(int), typeof(CardSelectionControl), new PropertyMetadata(0));
public CardSelectionControl()
{
DataContext = this;
InitializeComponent();
}
}
}
我假设你希望你的 setter 被调用,因此你为什么到处调用 OnPropertyChanged
。 They don't get called 所以你的代码不会被执行。
相反,您可以向依赖项属性添加回调,以便您知道值何时更改:
public static readonly DependencyProperty LevelProperty =
DependencyProperty.Register("Level",
typeof(int),
typeof(CardSelectionControl),
new PropertyMetadata(10, new PropertyChangedCallback(OnChanged)));
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
private static void OnChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var cardSelectionControl = (CardSelectionControl)d;
cardSelectionControl.Recalculate();
}
我冒昧地将 OnPropertyChanged
更改为 Recalculate
,并为组合框添加了 PropertyChangedCallback
,整个代码变为:
public partial class CardSelectionControl : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public int Level
{
get { return (int)GetValue(LevelProperty); }
set { SetValue(LevelProperty, value); }
}
public int SelectedIndex
{
get { return (int)GetValue(SelectedIndexProperty); }
set { SetValue(SelectedIndexProperty, value); }
}
public int Result
{
get { return (int)GetValue(ResultProperty); }
set { SetValue(ResultProperty, value); }
}
public void Recalculate()
{
if (SelectedIndex == 0)
Result = Level * 2;
else if (SelectedIndex == 1)
Result = Level * 3;
}
public static readonly DependencyProperty ResultProperty =
DependencyProperty.Register("Result", typeof(int), typeof(CardSelectionControl), new PropertyMetadata(20));
public static readonly DependencyProperty LevelProperty =
DependencyProperty.Register("Level", typeof(int), typeof(CardSelectionControl), new PropertyMetadata(10, new PropertyChangedCallback(OnChanged)));
public static readonly DependencyProperty SelectedIndexProperty =
DependencyProperty.Register("SelectedIndex", typeof(int), typeof(CardSelectionControl), new PropertyMetadata(0, new PropertyChangedCallback(OnChanged)));
private static void OnChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var cardSelectionControl = (CardSelectionControl)d;
cardSelectionControl.Recalculate();
}
public CardSelectionControl()
{
DataContext = this;
InitializeComponent();
}
}
我正在尝试在 WPF 中创建一个用户控件(使用 xceed)。我有一个组合框和一个 integerUpDown。
标签应在其中一个更改其值时更改其内容。第一个标签只有一个简单的绑定到 integerUpDown,这是有效的。 Visual Studio 自动创建了 OnPropertyChanged()
和 getters/setters,我尝试使用它将我的结果绑定到第二个标签,但它不起作用。没有任何反应。
这是我的 XAML:
<UserControl x:Class="WpfApp2.CardSelectionControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfApp2" xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<StackPanel Margin="5" Width="300" Height="400" Background="LightGray">
<TextBox Margin="5" AcceptsReturn="True" FontSize="20" Padding="5" Height="70">placeholding</TextBox>
<ComboBox SelectedIndex="{Binding SelectedIndex}" Background="Red" Margin="5">
<ComboBoxItem Content="card1"></ComboBoxItem>
<ComboBoxItem Content="card2"></ComboBoxItem>
</ComboBox>
<xctk:UIntegerUpDown Margin="5" x:Name="upDown" Value="{Binding Level}" ></xctk:UIntegerUpDown>
<Label Height="50" Content="{Binding Level}"></Label>
<Label Height="50" Content="{Binding Result}" ></Label>
</StackPanel>
</UserControl>
后面的代码:
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;
namespace WpfApp2
{
public partial class CardSelectionControl : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public int Level
{
get { OnPropertyChanged(); return (int)GetValue(LevelProperty); }
set
{
OnPropertyChanged();
SetValue(LevelProperty, value);
}
}
public int SelectedIndex
{
get { OnPropertyChanged(); return (int)GetValue(SelectedIndexProperty); }
set
{
OnPropertyChanged();
SetValue(SelectedIndexProperty, value);
}
}
public int Result
{
get { return (int)GetValue(ResultProperty); }
set { SetValue(ResultProperty, value); }
}
protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
if (SelectedIndex == 0)
{ Result = Level * 2; }
else if (SelectedIndex == 1)
{ Result = Level * 3; }
}
public static readonly DependencyProperty ResultProperty =
DependencyProperty.Register("Result", typeof(int), typeof(CardSelectionControl), new PropertyMetadata(20));
public static readonly DependencyProperty LevelProperty =
DependencyProperty.Register("Level", typeof(int), typeof(CardSelectionControl), new PropertyMetadata(10));
public static readonly DependencyProperty SelectedIndexProperty =
DependencyProperty.Register("SelectedIndex", typeof(int), typeof(CardSelectionControl), new PropertyMetadata(0));
public CardSelectionControl()
{
DataContext = this;
InitializeComponent();
}
}
}
我假设你希望你的 setter 被调用,因此你为什么到处调用 OnPropertyChanged
。 They don't get called 所以你的代码不会被执行。
相反,您可以向依赖项属性添加回调,以便您知道值何时更改:
public static readonly DependencyProperty LevelProperty =
DependencyProperty.Register("Level",
typeof(int),
typeof(CardSelectionControl),
new PropertyMetadata(10, new PropertyChangedCallback(OnChanged)));
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
private static void OnChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var cardSelectionControl = (CardSelectionControl)d;
cardSelectionControl.Recalculate();
}
我冒昧地将 OnPropertyChanged
更改为 Recalculate
,并为组合框添加了 PropertyChangedCallback
,整个代码变为:
public partial class CardSelectionControl : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public int Level
{
get { return (int)GetValue(LevelProperty); }
set { SetValue(LevelProperty, value); }
}
public int SelectedIndex
{
get { return (int)GetValue(SelectedIndexProperty); }
set { SetValue(SelectedIndexProperty, value); }
}
public int Result
{
get { return (int)GetValue(ResultProperty); }
set { SetValue(ResultProperty, value); }
}
public void Recalculate()
{
if (SelectedIndex == 0)
Result = Level * 2;
else if (SelectedIndex == 1)
Result = Level * 3;
}
public static readonly DependencyProperty ResultProperty =
DependencyProperty.Register("Result", typeof(int), typeof(CardSelectionControl), new PropertyMetadata(20));
public static readonly DependencyProperty LevelProperty =
DependencyProperty.Register("Level", typeof(int), typeof(CardSelectionControl), new PropertyMetadata(10, new PropertyChangedCallback(OnChanged)));
public static readonly DependencyProperty SelectedIndexProperty =
DependencyProperty.Register("SelectedIndex", typeof(int), typeof(CardSelectionControl), new PropertyMetadata(0, new PropertyChangedCallback(OnChanged)));
private static void OnChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var cardSelectionControl = (CardSelectionControl)d;
cardSelectionControl.Recalculate();
}
public CardSelectionControl()
{
DataContext = this;
InitializeComponent();
}
}