上下文菜单绑定到父窗口的数据上下文

6

我有一个TreeListControl,它绑定到我的VM中的一个集合。我还想在treelistcontrol内定义上下文菜单,使其标题文本绑定到我的VM中的另一个字符串。在这种情况下,我该如何设置数据上下文?我尝试过

<Window.DataContext>
    <model:ViewModel></model:ViewModel>
</Window.DataContext>
<Grid>
<Button Grid.Row="1"  Command="{Binding CellCheckedCommand}"></Button>

    <TextBlock Text="{Binding HeaderText}" Grid.Row="2">
        <TextBlock.ContextMenu>
            <ContextMenu>
                <MenuItem DataContext="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=DataContext}"  Header="{Binding HeaderText}"></MenuItem>
            </ContextMenu>
        </TextBlock.ContextMenu>
    </TextBlock>
</Grid>

但是它无法正常工作。
这里是ViewModel。
public DelegateCommand CellCheckedCommand { get; set; }

private String _HeaderText;

public String HeaderText 
{
    get
    {
        return _HeaderText;
    }
    set
    {
        _HeaderText = value;
        NotifyPropertyChanged("HeaderText");
    }
}

public void NotifyPropertyChanged(String name)
{ 
    if(PropertyChanged != null)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(name));
    }
}

private void CellCheckedMethod()
{
    HeaderText = "Changed";
}

你正在应对两个问题,上下文菜单(cm)的本质和它所在的父级。仅有CM可能会超出其内部可视树范围。但是一旦将CM放置在没有可视树的对象上(例如树列表或数据网格中的某些项目),就必须尝试找到页面的可视树。你已经了解了绑定,但每个控件都有自己的特殊性。也许可以扩展树项数据类以指向当前VM(?)。这样,绑定就可以访问当前VM而无需跳过障碍。 - ΩmegaMan
数据绑定的最简明文本可在MSDN上找到:数据绑定概述 - ΩmegaMan
2个回答

5

这将绑定到一个窗口:

DataContext="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}}"

如果在Window ViewModel中定义了AddItemCommand命令和AddItemText属性,绑定到Window DataContext。
DataContext="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=DataContext}"

它不能工作,请看我的示例:<TextBlock Text=" {Binding HeaderText}" Grid.Row="2"> <TextBlock.ContextMenu> <ContextMenu> <MenuItem DataContext="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=DataContext}"
Header="{Binding HeaderText}"></MenuItem> </ContextMenu> </TextBlock.ContextMenu> </TextBlock>
- Helic
@Helic,有助于解决问题的是你的ViewModel的简短版本 - 其中包含HeaderText、AddItemText和AddItemCommand属性,因为仅从.xamls无法确定你试图实现什么。 - lisp
+1 对于相对路径的示例。我已将其添加到我的第二个更新中。 - ΩmegaMan
2
这不起作用是因为ContextMenu不在可视树中,所以它永远找不到x:Type Window。 - user99999991

4
提供一个窗口名称并显式绑定,例如:
<window  x:Name="ReportsPage"/>

...

 <MenuItem DataContext="{Binding ElementName=ReportsPage}"/>

更新

由于上下文菜单实际上是在它自己的窗口中,所以绑定稍微有点棘手。因此,最好的方法是向上遍历RelativeSource以获取上下文的父级,并从那里提取标题文本:

    <Window.DataContext>
        <local:MainVM HeaderText="Jabberwocky" />
    </Window.DataContext>

    ...

<TextBlock Text="{Binding HeaderText}">
    <TextBlock.ContextMenu>
        <ContextMenu>

<MenuItem Header="{Binding Path=Parent.DataContext.HeaderText, 
                    RelativeSource={RelativeSource Self}}" />

        </ContextMenu>
    </TextBlock.ContextMenu>

在这种情况下,它会产生这个结果:

输入图像描述


@Helic 添加 Path=DataContext - ΩmegaMan
@Helic 我没有完全使用 DataContext 来限定绑定。请看我的更新。 - ΩmegaMan
非常感谢提供不同的解决方案。您所说的最后一个解决方案中的设计时间是什么意思?此外,我尝试将它们与ContextItem的Header一起使用,但它们都无法正常工作,但对于TextBlock却可以。 - Helic
@Helic 抱歉,我离开了你的完美示例以追求速度。在这种情况下,您不需要代理。请查看我提供的更新示例,使用RelativeSource绑定到自身并进入包含页面上下文的父级数据上下文。 - ΩmegaMan
你的意思是对于任何弹出窗口,我们不能使用正常的数据绑定方法,而是需要将其绑定到主窗口的可视树中的一个项目,并借用它的数据上下文吗?我可能理解错了。 - Helic
显示剩余7条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接