1

我想使用 4 个文本框设置用户控件的边框的 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 不会导致边框左侧的呈现方式发生变化。奇怪的是,我在 TextBox 中为 Thickness.Left 设置的值仍然存在,所以看起来该值确实被设置了,但渲染没有更新。在示例代码中,更改 TextBox 中的值,然后调整 Window 大小,显示左侧边框确实占用了额外的空间,但该空间是空白的。

有谁知道如何解决这个问题?

4

3 回答 3

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");
        }
    }
}
于 2010-10-13T18:25:45.737 回答
1

我相信这将为您指明正确的方向:读到一半,它有两种方法可以解决这个问题,一种带有转换器,另一种没有。

http://10rem.net/blog/2010/05/08/break-apart-the-margin-property-in-xaml-for-better-binding

于 2010-10-13T15:57:56.493 回答
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;
};

现在这对我有用,罗伯特罗斯尼的解决方案更好。

于 2010-10-14T12:36:39.393 回答