未从ViewModel

时间:2017-06-01 07:50:54

标签: c# wpf xaml binding custom-controls

我创建了一个自定义控件" CustomAutoCompleteBox" (继承AutoCompleteBox)有一个依赖属性" CurrentItem"。

public static readonly DependencyProperty CurrentItemProperty =
        DependencyProperty.Register("CurrentItem", typeof(CityEntity), typeof(CustomAutoCompleteBox),
            new FrameworkPropertyMetadata(
                null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

    public CityEntity CurrentItem
    {
        get { return (CityEntity)GetValue(CurrentItemProperty); }
        set { SetValue(CurrentItemProperty, value); }
    }

此自定义控件还具有属性" InternalCurrentItem"。

public CityEntity InternalCurrentItem
    {
        get { return _internalCurrentCity; }

        set
        {
            if (_internalCurrentCity == value) return;

            _internalCurrentCity = value;
            OnPropertyChanged();

            CurrentItem = value;
        }
    }

DataContext在构造函数中定义为自己:

public VilleAutoCompleteBox()
    {
        DataContext = this;

        ...
    }

Style设置了ItemsSource和SelectedItem,如下所示:

<Style TargetType="{x:Type infrastructure_controls:CustomAutoCompleteBox}" BasedOn="{StaticResource AutoCompleteBoxFormStyle}">
    <Setter Property="ItemsSource" Value="{Binding InternalItems, Mode=OneWay}" />
    <Setter Property="SelectedItem" Value="{Binding InternalCurrentItem, Mode=TwoWay}" />
    ...
</Style>

总之,ItemsSource绑定到内部属性&#34; InternalItems&#34;和SelectedItem绑定到内部属性&#34; InternalCurrentItem&#34;。

为了使用它,我声明这个CustomAutoCompleteBox如下:

<infrastructure_usercontrols:CustomAutoCompleteBox Width="200" CurrentItem="{Binding DataContext.VmCurrentItem, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Mode=TwoWay}" />

我绑定了依赖属性&#34; CurrentItem&#34;到ViewModel的属性&#34; VmCurrentItem&#34;。

除了一件事以外,一切正常。

当我在控件中键入文本时,InternalCurrentItem属性会正确更改。与我的ViewModel中的CurrentItem属性相同。

具体而言,正确修改了InternalCurrentItem(Set)。此属性设置CurrentItem依赖项属性,此依赖项属性设置VmCurrentItem。

反之则不然。如果我直接更改ViewModel中VmCurrentItem属性的值,则不会更改CurrentItem属性。我不明白为什么。

2 个答案:

答案 0 :(得分:1)

第一种情况会导致以下事件链:

  • SelectedItem已更改
  • 由于绑定,
  • InternalCurrentItem由框架更新
  • 您在CurrentItem setter
  • 中手动更新InternalCurrentItem 由于绑定,
  • VmCurrentItem由框架更新

相反的方向就是这样:

  • VmCurrentItem已更改
  • 由于绑定,
  • CurrentItem由框架更新

......就是这样。当InternalCurrentItem发生变化时,没有任何约束,也没有任何代码可以更新CurrentItem。因此,您需要为PropertyChangedCallback注册一个CurrentItemProperty,这将更新InternalCurrentItem

public static readonly DependencyProperty CurrentItemProperty =
    DependencyProperty.Register(
        "CurrentItem",
        typeof(CityEntity),
        typeof(CustomAutoCompleteBox),
        new FrameworkPropertyMetadata
        {
            BindsTwoWayByDefault = true,
            PropertyChangedCallback = CurrentItemPropertyChanged
        });

private static void CurrentItemPropertyChanged(
     DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    var control = (CustomAutoCompleteBox)d;
    control.InternalCurrentItem = (CityEntity)e.NewValue;
}

答案 1 :(得分:0)

您需要以与第一个相同的方式声明属性:

public static readonly DependencyProperty InternalCurrentItemProperty =
        DependencyProperty.Register("InternalCurrentItem", typeof(CityEntity), typeof(CustomAutoCompleteBox),
            new FrameworkPropertyMetadata(
                null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

public CityEntity InternalCurrentItem
{
    get{ return (CityEntity)GetValue(InternalCurrentItemProperty); }

    set
    {
        SetValue(InternalCurrentItemProperty, value);
    }
}
相关问题