如果绑定,属性将不会更新它的值

时间:2012-12-11 14:49:47

标签: silverlight windows-phone

我需要一个只显示所选项目的ItemsControl,所以我写了一个自定义的ItemsControl,如下所示:

public class TabView : ItemsControl
{
    public static readonly DependencyProperty SelectedItemProperty = 
        DependencyProperty.Register(
            "SelectedItem",
            typeof(object),
            typeof(TabView),
            new PropertyMetadata(new PropertyChangedCallback(SelectedItemPropertyChanged)));
    private static void SelectedItemPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        //throw new NotImplementedException();
    }

    public object SelectedItem
    {
        get { return GetValue(SelectedItemProperty); }
        set { OnSelectedItemChanged(value); }
    }

    public TabView()
        : base()
    {
    }

    protected override void OnItemsChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        base.OnItemsChanged(e);

        if (!IsItem(SelectedItem))
        {
            if (Items.Count > 0)
                SelectedItem = Items[0];
            else
                SelectedItem = null;
        }
    }

    protected override bool IsItemItsOwnContainerOverride(object item)
    {
        return false;
    }

    protected override DependencyObject GetContainerForItemOverride()
    {
        Grid grid = new Grid();
        grid.VerticalAlignment = System.Windows.VerticalAlignment.Stretch;
        grid.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;

        return grid;
    }

    protected virtual void OnSelectedItemChanged(object newItem)
    {
        if (SelectedItem == newItem) return;

        if (!IsItem(newItem))
        {
            Debugger.Log(0, "TRACE", "TABVIEW: Index Out of Bounds"+Environment.NewLine);
            return;
        }


        foreach (var item in Items)
        {
            var container = ItemContainerGenerator.ContainerFromItem(item);
            if (container != null)
            {
                if (item == newItem)
                    container.SetValue(Control.VisibilityProperty, Visibility.Visible);
                else
                    container.SetValue(Control.VisibilityProperty, Visibility.Collapsed);
            }
        }

        SetValue(SelectedItemProperty, newItem);
    }

    private bool IsItem(object item)
    {
        return Items.Contains(item);
    }

}

现在我将我的Dataobject SelectedDataTab (MainViewModel.SelectedDataTab)绑定到TabView.SelectedItem。

        <uc:TabView 
            ItemsSource="{Binding BrowserTabs}" 
            SelectedItem="{Binding SelectedDataTab}">

            <uc:TabView.ItemTemplate>
                <DataTemplate>
                    <local:SlitteTabViewSelector Content="{Binding}" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch">
                        <local:SlitteTabViewSelector.Browser>
                            <DataTemplate>
                                <uc:CustomBrowser Margin="0,0,0,0" />
                            </DataTemplate>
                        </local:SlitteTabViewSelector.Browser>
                        <local:SlitteTabViewSelector.MoreTabs>
                            <DataTemplate>
                                <uc:MoreTabsControl Margin="0,0,0,0" />
                            </DataTemplate>
                        </local:SlitteTabViewSelector.MoreTabs>
                    </local:SlitteTabViewSelector>
                </DataTemplate>
            </uc:TabView.ItemTemplate>

        </uc:TabView>

如果我现在开始在MainViewModel中更改 SelectedDataTab TabView.SelectedItem 将不会更改其值!我错过了什么?我想如果我将该属性绑定到我的MainViewModel.SelectedDataTab,它的值会根据绑定值进行更新。

更新:我的MainViewModel正确实现了INotifyPropertyChanged,如果更改,SelectedDataTab将触发它。

1 个答案:

答案 0 :(得分:0)

<强>分辨 首先,Binding不会触发Property getter / setter,而是触发SelectedItemPropertyChanged。

但在我的代码中,SelectedItemPropertyChanged不会被解雇,因为

protected override void OnItemsChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
    base.OnItemsChanged(e);

    if (!IsItem(SelectedItem))
    {
        if (Items.Count > 0)
            SelectedItem = Items[0];
        else
            SelectedItem = null;
    }
}

覆盖DataBinding。 ;)