【发布时间】:2022-01-18 06:01:14
【问题描述】:
这部分代码用于更新 C# WPF 中文本框中数字的显示。
CS:
namespace BindTest
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public BindInt x1 = new BindInt(0);
public MainWindow()
{
InitializeComponent();
Test1_Tbox.DataContext = x1;
}
private void Up_Btn_Click(object sender, RoutedEventArgs e)
{
x1.Number += 1;
}
private void Dn_Btn_Click(object sender, RoutedEventArgs e)
{
x1.Number -= 1;
}
}
public class BindInt : INotifyPropertyChanged
{
// integer class with property change notification for binding
private int number;
public event PropertyChangedEventHandler PropertyChanged;
public BindInt()
{
number = 0;
OnPropertyChanged("Number");
}
public BindInt(int Val)
{
number = Val;
OnPropertyChanged("Number");
}
public int Number
{
get { return this.number; }
set
{
if (number != value)
{
number = value;
OnPropertyChanged(nameof(Number));
}
}
}
protected void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
XAML:
<Window x:Class="BindTest.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:BindTest"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<TextBox x:Name="Test1_Tbox"
HorizontalAlignment="Left"
Margin="10,10,0,0"
Text="{Binding Number, Mode=OneWay, StringFormat=\{0:D\}}"
TextWrapping="Wrap"
VerticalAlignment="Top" Width="120"/>
<Button x:Name="Up_Btn" Click="Up_Btn_Click" Content="Up" HorizontalAlignment="Left" Margin="550,124,0,0" VerticalAlignment="Top" Width="50" Height="20"/>
<Button x:Name="Dn_Btn" Click="Dn_Btn_Click" Content="Down" HorizontalAlignment="Left" Margin="550,164,0,0" VerticalAlignment="Top" Width="50" Height="20"/>
</Grid>
</Window>
所以现在我可以在单击按钮时看到显示的值更新。
在我的实际应用程序中,我需要执行以下操作:
- 显示值如上。
- 使多个控件可见或隐藏以及启用或禁用。
目前,我只是直接写入每个控件的可见性属性,但由于控件的数量,这变得笨拙。我正在寻找的是一种方法:
- 将文本值绑定到一个属性(例如上例中的 x1.Number)。
- 将可见性绑定到另一个属性。
- 可能将 Enabled 绑定到另一个属性。
我尝试了许多绑定组合,但似乎唯一对我有用的就是上面的安排 - 在代码隐藏中设置 DataContext 并绑定到 x1 的 Number 属性。
有没有一种很好的通用方法来以这种方式绑定?如果我可以将 DataContext 设置为 MainWindow 类,然后绑定到例如 x1.Number,那么这可能会满足我的需求。
更新了我的最终解决方案:
最后,我找到了另一个更简单的答案。对于常用的可见性绑定,我使用了一个 DependencyProperty,如下所示。每个需要被公共控件设置为可见/隐藏的控件都绑定到 DIAGenable。
CS 片段:
public static readonly DependencyProperty DIAGEnableProperty =
DependencyProperty.Register("DIAGEnable", typeof(bool),
typeof(MainWindow), new FrameworkPropertyMetadata(true,
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
public bool DIAGEnable
{
get
{
return (bool)GetValue(DIAGEnableProperty);
}
set
{
SetValue(DIAGEnableProperty, value);
}
}
典型 XAML:
<TextBox x:Name="RuntimeTbox" Grid.Column="1" HorizontalAlignment="Left" Height="40" Margin="385,657,0,0"
TextWrapping="Wrap" Text="{Binding Path=Number, Mode=OneWay, StringFormat=\{0:F\}}" VerticalAlignment="Top"
Width="108" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" FontSize="16"
FontWeight="Bold" Background="#FFF0F0F0" Focusable="False"
Visibility="{Binding Path=DIAGEnable, Converter={StaticResource BooleanToVisibilityConverter}, ElementName=MainWin}"
IsEnabled="{Binding Path=DIAGEnable, ElementName=MainWin}"/>
我仍然无法在 CodeBehind 中使用这一行:
Test1_Tbox.DataContext = x1;
设置DataContext绑定x1.Number的文本值。 无论我尝试什么,我的代码都没有接受 XAML 中定义的 WPF 控件的通用 DataContext。
【问题讨论】:
-
您的视图模型类 (BindInt) 当然可能会公开多个属性,这些属性的实现方式是,当一个属性发生变化时,其他属性也会发生变化。在属性 B 的 setter 中简单更新属性 A。“从属”属性也可以只读方式实现(只有一个 getter),其中控制属性的 setter 执行多个 OnPropertyChanged 调用。
-
另外,您可以将多个 UI 元素绑定到单个源属性并使用绑定转换器,或者在元素样式中使用 DataTriggers。
-
请注意,在视图模型构造函数中调用 OnPropertyChanged 是没有意义的。
-
在已编辑的问题中查看我的最终解决方案