WPF绑定属性不会更新源值

时间:2018-03-26 05:16:55

标签: c# wpf data-binding

我的自定义控件中有DependencyProperty。我将它绑定到某个对象中的某个属性。当我的控件出现时,它从源获取值并将其应用于自身。但是当我在输入字段中输入内容时,源值不会改变。我做错了什么?

控制声明:

public class ScriptComponentField : Control
{
    public enum Datatype
    {
        String,
        Integer,
        Real,
        Boolean,
        Enumerable,
        Code
    }

    public string Header
    {
        get { return (String)GetValue(HeaderProperty); }
        set { SetValue(HeaderProperty, value); }
    }
    public static readonly DependencyProperty HeaderProperty = DependencyProperty.RegisterAttached(nameof(Header), typeof(string), typeof(ScriptComponentField), new PropertyMetadata(""));

    public object Value
    {
        get { return GetValue(ValueProperty); }
        set { SetValue(ValueProperty, value); }
    }
    public static readonly DependencyProperty ValueProperty = DependencyProperty.RegisterAttached(nameof(Value), typeof(object), typeof(ScriptComponentField), new PropertyMetadata(null));

    public Datatype ValueType
    {
        get { return (Datatype)GetValue(ValueTypeProperty); }
        set { SetValue(ValueTypeProperty, Value); }
    }
    public static readonly DependencyProperty ValueTypeProperty = DependencyProperty.RegisterAttached(nameof(ValueType), typeof(Datatype), typeof(ScriptComponentField), new PropertyMetadata(Datatype.String));

    public List<string> EnumerableItems
    {
        get { return (List<string>)GetValue(EnumerableItemsProperty); }
        set { SetValue(EnumerableItemsProperty, Value); }
    }
    public static readonly DependencyProperty EnumerableItemsProperty = DependencyProperty.RegisterAttached(nameof(EnumerableItems), typeof(List<string>), typeof(ScriptComponentField), new PropertyMetadata(null));

    static ScriptComponentField()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(ScriptComponentField), new FrameworkPropertyMetadata(typeof(ScriptComponentField)));
    }
}

属性Value只有object类型,因为它可以包含stringboolint等任何值。

控制模板:

<Style TargetType="{x:Type Controls:ScriptComponentField}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Controls:ScriptComponentField}">
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="150" SharedSizeGroup="name"/>
                        <ColumnDefinition SharedSizeGroup="value"/>
                    </Grid.ColumnDefinitions>
                    <Label Content="{TemplateBinding Header}" HorizontalAlignment="Right" VerticalAlignment="Center"/>
                    <TextBox x:Name="InputString" Visibility="Collapsed" Grid.Column="1" Text="{TemplateBinding Value}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" VerticalContentAlignment="Center" Margin="0,2"/>
                    <Advanced:IntegerUpDown x:Name="InputInteger" Visibility="Collapsed" Grid.Column="1" Value="{TemplateBinding Value}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" VerticalContentAlignment="Center" Margin="0,2"/>
                    <CheckBox x:Name="InputBoolean" Visibility="Collapsed" Grid.Column="1" IsChecked="{TemplateBinding Value}" VerticalAlignment="Center"/>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="ValueType" Value="String">
                        <Setter TargetName="InputString" Property="Visibility" Value="Visible"/>
                    </Trigger>
                    <Trigger Property="ValueType" Value="Integer">
                        <Setter TargetName="InputInteger" Property="Visibility" Value="Visible"/>
                    </Trigger>
                    <Trigger Property="ValueType" Value="Boolean">
                        <Setter TargetName="InputBoolean" Property="Visibility" Value="Visible"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

2 个答案:

答案 0 :(得分:1)

问题是你使用TemplateBindingOneWay始终为TemplateBinding。如果您使用TwoWayBindingRelativeSource更改为ElementName <TextBox x:Name="InputString" Visibility="Collapsed" Grid.Column="1" Text="{Binding Value, RelativeSource={RelativeSource AncestorType=Controls:ScriptComponentField}, Mode=TwoWay}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" VerticalContentAlignment="Center" Margin="0,2"/> ,则可以使用ALTER INDEX my_index_i MONITORING USAGE; ALTER INDEX my_index_i NOMONITORING USAGE;

v$object_usage

答案 1 :(得分:0)

您可能错过了“Mode = TwoWay”属性,如下所示:

<Button x:Name="btnMy" Content="{Binding MyText, Mode=TwoWay}" />

默认控件绑定是“OneWay”(参见下面的编辑),“当绑定源(源)发生更改时,更新绑定目标(目标)属性。” ©MSDN链接

TwoWay绑定:“导致更改源属性或目标属性以自动更新其他”©MSDN链接

MSDN BindingMode

编辑:

正如Clemens所述,关于默认绑定模式: “默认模式是在注册属性期间通过FrameworkPropertyMetadataOptions设置的。” ©Clemens
简而言之,它并不总是OneWay,而是大部分时间。