如何在datacontext设置为祖先时设置绑定

时间:2015-02-04 18:53:32

标签: wpf mvvm

我想知道如何在Viewmodel WorkTabViewModel中设置绑定到公共变量。我设置了两个我在下面尝试的例子,

Foreground="{Binding MenuItemForeground}"

Foreground="{Binding MenuItemForeground, RelativeSource={RelativeSource AncestorType=UserControl}}"

但是他们都不认识MenuItemForeground。

<TextBlock VerticalAlignment="Center" FontWeight="Bold" Margin="1 0 0 0" DataContext="{Binding Path=DataContext, RelativeSource={RelativeSource AncestorType=UserControl}}" >
    <TextBlock.ContextMenu>
        <ContextMenu>
            <MenuItem Header="Close tab" cal:Message.Attach="[Click] = [CloseTab()]" />
            <MenuItem Header="Close other tabs" cal:Message.Attach="[Click] = [CloseOtherTabs()]" IsEnabled="False" Foreground="{Binding MenuItemForeground, RelativeSource={RelativeSource AncestorType=UserControl}}"/>
            <MenuItem Header="Close all tabs" cal:Message.Attach="[Click] = [CloseAllTabs()]" IsEnabled="False" Foreground="{Binding MenuItemForeground}"/>
         </ContextMenu>
    </TextBlock.ContextMenu>
</TextBlock>

WorkTabViewModel

public Brush MenuItemForeground { get; set; }
public void CloseTab(){...}
public void CloseOtherTab(){...}
public void CloseAllTabs(){...}

1 个答案:

答案 0 :(得分:0)

上下文菜单不是可视树的一部分,因此它不会继承父控件DataContext。由于这个原因,您也无法使用祖先语法。

一种解决方案是使用绑定代理。

public class BindingProxy : Freezable
{
    #region Overrides of Freezable

    protected override Freezable CreateInstanceCore()
    {
        return new BindingProxy();
    }

    #endregion

    public object Data
    {
        get { return (object)GetValue(DataProperty); }
        set { SetValue(DataProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Data.
    // This enables animation, styling, binding, etc...
    public static readonly DependencyProperty DataProperty =
        DependencyProperty.Register("Data",
                                    typeof(object),
                                    typeof(BindingProxy),
                                    new UIPropertyMetadata(null));
}

它在XAML中的用法。

<TextBlock VerticalAlignment="Center" 
           FontWeight="Bold" 
           Margin="1 0 0 0"
           DataContext="{Binding Path=DataContext, RelativeSource={RelativeSource AncestorType=UserControl}}">
    <TextBlock.Resources>
        <helper:BindingProxy x:Key="proxy"
                             Data="{Binding }" />
    </TextBlock.Resources>
    <TextBlock.ContextMenu>
        <MenuItem Header="Close tab" 
                  cal:Message.Attach="[Click] = [CloseTab()]" />
        <MenuItem Header="Close other tabs" 
                  cal:Message.Attach="[Click] = [CloseOtherTabs()]"
                  IsEnabled="False"
                  Foreground="{Binding Source={StaticResource proxy}, Data.MenuItemForeground}"/>
        <MenuItem Header="Close all tabs" 
                  cal:Message.Attach="[Click] = [CloseAllTabs()]"
                  IsEnabled="False"
                  Foreground="{Binding Source={StaticResource proxy}, Data.MenuItemForeground}"/>
     </ContextMenu>
</TextBlock.ContextMenu>

不要忘记在Window / UserControl的顶部声明帮助程序名称空间导入。