【问题标题】:how to set bindings when datacontext is set to ancestor当数据上下文设置为祖先时如何设置绑定
【发布时间】:2015-02-04 18:53:31
【问题描述】:

我想知道如何将绑定设置为我的 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>

工作表视图模型

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

【问题讨论】:

  • 如果父 DataContext 实际设置为 WorkTabViewModel 的实例,并且 MenuItemForeground 属性具有值,则表达式 Foreground="{Binding MenuItemForeground}" 应该可以工作。第二次尝试是错误的。此外,TextBlock 上的DataContext="{Binding Path=DataContext, ...}" 是多余的,因为父 DataContext 被继承给子元素。
  • 嗨 Clemens,当我设置 MenuItemForeground 时,它显示无法在“对象”类型的数据上下文中解析属性“menuitemforground”。它指向 WorkTabViewModel 并且可以工作,因为它会触发 closetab() 和其他函数。
  • 试试看。 Foreground="{Binding DataContext.MenuItemForeground,RelativeSource={RelativeSource AncestorType=UserControl}}"

标签: wpf mvvm


【解决方案1】:

上下文菜单不是可视化树的一部分,因此它不会继承父控件 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 的顶部声明 helper 命名空间导入。

【讨论】:

  • 嗨,李,感谢您帮助我。非常感谢您的帮助。我尝试了你的方法并产生了这个错误A first chance exception of type 'System.Windows.Markup.XamlParseException' occurred in PresentationFramework.dll Additional information: Cannot call MarkupExtension.ProvideValue because of a cyclical dependency. Properties inside a MarkupExtension cannot reference objects that reference the result of the MarkupExtension. The affected MarkupExtensions are: System.Windows.Data.Binding System.Windows.Data.Binding
  • 好吧...我不知道这个限制 (stackoverflow.com/questions/12871551/…)。我会用另一个选项更新。
  • 嗨,李,很抱歉回复晚了。我尝试了你的方法,但仍然没有=(相同的结果。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-05
  • 2020-06-10
  • 2012-04-01
  • 1970-01-01
相关资源
最近更新 更多