我想使用4个TextBox来设置UserControl边框的BorderThickness,但我无法让它工作。
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>
需要一个转换器来解析TextBox中的字符串输入:
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;
}
}
TextBox正确显示厚度的左侧部分,但编辑TextBox不会导致渲染边框左侧的方式发生变化。奇怪的是,我在ThickBox.Left的TextBox中设置的值仍然存在,因此似乎设置了值,但渲染未更新。 在示例代码中,更改TextBox中的值,然后调整Window的大小,显示左侧的边框确实占用了额外的空间,但此空格为空。
有谁知道如何解决这个问题?
答案 0 :(得分:2)
它不会动态更新屏幕上的元素,因为没有任何内容告诉元素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");
}
}
}
答案 1 :(得分:1)
我相信这会指引你朝着正确的方向前进:在中途阅读有两种方法可以接近这种方式,一种方式使用转换器而一种方式不使用。
http://10rem.net/blog/2010/05/08/breaking-apart-the-margin-property-in-xaml-for-better-binding
答案 2 :(得分:0)
对我来说,最简单的解决方案是只听取TextBox的TextChanged事件,并替换后面代码中的BorderThickness。
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;
};
现在这对我有用,Robert Rossney的解决方案更好。