如何使用自定义属性设置数据绑定



我在WPF中创建了一个简单的spinbox(numericUpDown)控件(因为没有)。

我已经创建了一个自定义 Value 属性,我想使用 Model 创建一个数据绑定。

<UserControl x:Class="PmFrameGrabber.Views.SpinBox"
         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:PmFrameGrabber.Views"
         mc:Ignorable="d" 
         d:DesignHeight="25" d:DesignWidth="100">
<UserControl.Resources>
    <local:IntToStringConv x:Key="IntToStringConverter" />
</UserControl.Resources>
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition />
        <ColumnDefinition Width="25" />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition />
        <RowDefinition />
    </Grid.RowDefinitions>
    <TextBox Name="TbValue" Grid.RowSpan="2" HorizontalContentAlignment="Right" 
             VerticalContentAlignment="Center" HorizontalAlignment="Stretch" 
             VerticalAlignment="Stretch" Text="{Binding Value, Converter={StaticResource IntToStringConverter}}"/>
    <Button Name="BtPlus" Grid.Column="1" Grid.Row="0" HorizontalAlignment="Stretch" Margin="3,0,0,0" 
            VerticalAlignment="Center" FontSize="8" Content="+" Click="BtPlus_Click" />
    <Button Name="BtMinus" Grid.Column="1" Grid.Row="1" HorizontalAlignment="Stretch" Margin="3,0,0,0"
            VerticalAlignment="Center" FontSize="8" Content="-" Click="BtMinus_Click" />
</Grid>
</UserControl>

下面是背后的代码:

public partial class SpinBox : UserControl
{
    public static DependencyProperty ValueDP =
        DependencyProperty.Register("Value", typeof(int), typeof(SpinBox), new UIPropertyMetadata(0));
    // Public bindable properties
    public int Value
    {
        get => (int)GetValue(ValueDP);
        set => SetValue(ValueDP, value);
    }
    public SpinBox()
    {
        InitializeComponent();
        DataContext = this;
    }
    private void BtPlus_Click(object sender, RoutedEventArgs e) => Value++;
    private void BtMinus_Click(object sender, RoutedEventArgs e) => Value--;
}

在另一种视图中,我尝试像这样使用控件:

<local:SpinBox Width="80" Height="25" Value="{Binding Cam.ExposureTime, Mode=TwoWay}" />

在这里我得到一个错误:Wpf绑定只能在依赖项对象的依赖项属性上设置

模型属性在 C++/CLI 中编写如下:

property int ExposureTime
{
     void set(int value)
     {
        m_settings->exposureTime = value;
        OnPropertyChanged(GetPropName(Camera, ExposureTime));
     }
     int get()
     {
         return m_settings->exposureTime;
     }
}

与此属性绑定适用于其他控件(文本框、标签)。

我想问题出在我的自定义 SpinBox 和我创建 Value 属性的方式上。经过一天的挖掘网络,我还没有找到其他事情可以做。

您忽略了依赖项属性命名约定,该约定要求必须将 DependencyProperty 字段命名为 <PropertyName>Property

public static readonly DependencyProperty ValueProperty =
    DependencyProperty.Register("Value", typeof(int), typeof(SpinBox));
public int Value
{
    get => (int)GetValue(ValueProperty);
    set => SetValue(ValueProperty, value);
}

除此之外,设置

DataContext = this;

构造函数阻止您可以绑定到继承的数据上下文。

像这样的绑定

<local:SpinBox Value="{Binding Cam.ExposureTime, Mode=TwoWay}" />

将不起作用,因为当前数据上下文中没有Cam属性。

因此,永远不要显式设置用户控件的 DataContext。

相反,请像这样编写"内部"绑定:

<TextBox Text="{Binding Value,
                RelativeSource={RelativeSource AncestorType=UserControl}, ...}" />

最新更新