WPF:在4个文本框和1个边框之间绑定二线。
-
29-09-2019 - |
题
我想使用4个文本框设置UserControl边界的边界,但我无法正常工作。
XAML代码证明了问题(仅需要与转换器结合使用此代码):
<Window
x:Class="BorderThicknessBindingTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:BorderThicknessBindingTest="clr-namespace:BorderThicknessBindingTest"
Height="300" Width="500">
<Window.Resources>
<BorderThicknessBindingTest:ThicknessConverter x:Key="ThicknessConverter"/>
</Window.Resources>
<Grid Margin="10">
<Border
x:Name="MyBorder"
BorderBrush="Black"
Background="AliceBlue"
BorderThickness="3"/>
<TextBox
HorizontalAlignment="Center" VerticalAlignment="Center"
Text="{Binding Path=BorderThickness.Left, ElementName=MyBorder, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource ThicknessConverter}}"/>
</Grid>
</Window>
需要一个转换器来解析文本框中的字符串输入:
public class ThicknessConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value; // don't need to do anything here
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
double d;
Double.TryParse((string) value, out d); // Thickness.Left doesn't take a string
return d;
}
}
文本框正确显示了厚度的左侧,但是编辑文本框不会导致边框左侧呈现的方式变化。奇怪的是,我在厚度的文本框中设置的值。左侧持续存在,因此似乎确实设置了值,但是渲染尚未更新。在示例代码中,更改文本框中的值,然后调整窗口大小,显示左侧的边框确实占用了其他空间,但是此空间为空白。
有人知道如何解决这个问题吗?
解决方案
它没有动态地更新屏幕上的元素,因为没有任何信息告诉元素 BorderThickness
属性已更改。您需要通知元素的 BorderThickness
已更改了,您只能通过将依赖项属性直接设置为新值来做到这一点 - 例如,将其成为绑定到确实更改通知的对象的目标。
为此建立视图模型是一件很痛苦的事情,但是一旦您完成了。
窗户:
<Window x:Class="ThicknessDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:ComponentModel="clr-namespace:System.ComponentModel;assembly=System" xmlns:ThicknessDemo="clr-namespace:ThicknessDemo" Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<ThicknessDemo:ThicknessViewModel x:Key="thickness" />
</Window.Resources>
<DockPanel DataContext="{StaticResource thickness}">
<Border DockPanel.Dock="Top"
Width="100"
Height="50"
Margin="5"
BorderBrush="Blue"
BorderThickness="{Binding Thickness}" />
<TextBox DockPanel.Dock="Top"
Text="{Binding Left, Mode=TwoWay}" />
<TextBox DockPanel.Dock="Top"
Text="{Binding Right, Mode=TwoWay}" />
<TextBox DockPanel.Dock="Top"
Text="{Binding Top, Mode=TwoWay}" />
<TextBox DockPanel.Dock="Top"
Text="{Binding Bottom, Mode=TwoWay}" />
<TextBlock DockPanel.Dock="Top" />
</DockPanel>
</Window>
视图模型:
public class ThicknessViewModel : INotifyPropertyChanged
{
private void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler h = PropertyChanged;
if (h != null)
{
h(this, new PropertyChangedEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
public ThicknessViewModel()
{
_Thickness = new Thickness(1, 1, 1, 1);
}
private Thickness _Thickness;
public Thickness Thickness { get { return _Thickness; } set { _Thickness = value;} }
public double Left
{
get { return _Thickness.Left; }
set
{
_Thickness.Left = value;
OnPropertyChanged("Thickness");
}
}
public double Right
{
get { return _Thickness.Right; }
set
{
_Thickness.Right = value;
OnPropertyChanged("Thickness");
}
}
public double Top
{
get { return _Thickness.Top; }
set
{
_Thickness.Top = value;
OnPropertyChanged("Thickness");
}
}
public double Bottom
{
get { return _Thickness.Bottom; }
set
{
_Thickness.Bottom = value;
OnPropertyChanged("Thickness");
}
}
}
其他提示
我相信这将指向您正确的方向:向下阅读它有两种接近此方法的方法,一个是带有转换器的方法,一个没有转换器。
对我而言,最简单的解决方案是只听文本框的文本变实事件,然后替换背后的代码中的边界键。
mainwindow.xaml:
<Window
x:Class="BorderThicknessBindingTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:BorderThicknessBindingTest="clr-namespace:BorderThicknessBindingTest"
Height="300" Width="500">
<Grid Margin="10">
<Border
x:Name="MyBorder"
BorderBrush="Black"
Background="AliceBlue"
BorderThickness="3"/>
<TextBox
x:Name="MyTextBox"
HorizontalAlignment="Center" VerticalAlignment="Center"
Text="{Binding Path=BorderThickness.Left, ElementName=MyBorder, Mode=OneWay}"/>
</Grid>
</Window>
mainwindow.xaml.cs,在构造函数中:
MyTextBox.TextChanged += (sender, e) =>
{
double d;
if (!double.TryParse(MyTextBox.Text, out d)) return;
var t = MyBorder.BorderThickness;
t.Left = d;
MyBorder.BorderThickness = t;
};
现在,这对我有用,罗伯特·罗斯尼的解决方案更好。
不隶属于 StackOverflow