【发布时间】:2016-06-08 08:55:33
【问题描述】:
X 问题。
我想暂时放大(让它占据整个可用空间)窗口内容的一部分。
窗口布局相当复杂:许多嵌套面板、拆分器、要放大的内容有 10 级深。将 Visibility 更改为拉伸内容是不够的(感谢拆分器),而且看起来非常复杂。
你的问题
我决定将该内容移动到用户控件中并执行类似(伪代码)之类的操作
if(IsEnlarged)
{
oldContent = window.Content; // store
window.Content = newContent;
}
else
window.Content = oldContent; // restore
没问题。它在测试项目中运行良好......直到我开始使用数据模板。
问题:如果使用数据模板,那么一旦出现window.Content = newContent,那么newContent.DataContext 就会丢失并与window.DataContext 相同。这将触发各种绑定错误,附加行为突然更改为默认值等等。所有类型的坏东西。
问题:为什么DataContext 会发生变化?如何预防/解决此问题?
这是一个复制品(抱歉,不能再短了):
MainWindow.xaml 包含
<Window.Resources>
<DataTemplate DataType="{x:Type local:ViewModel}">
<local:UserControl1 />
</DataTemplate>
</Window.Resources>
<Grid Background="Gray">
<ContentControl Content="{Binding ViewModel}" />
</Grid>
MainWindow.cs 包含
public ViewModel ViewModel { get; } = new ViewModel();
public MainWindow()
{
InitializeComponent();
DataContext = this;
}
UserControl1.xaml 包含
<Button Width="100"
Height="100"
CommandParameter="{Binding RelativeSource={RelativeSource Self}}"
Command="{Binding Command}" />
ViewModel(使用DelegateCommand)
public class ViewModel
{
public DelegateCommand Command { get; set; }
bool _set;
object _content;
public ViewModel()
{
Command = new DelegateCommand(o =>
{
var button = (Button)o;
var window = Window.GetWindow(button);
_set = !_set;
if (_set)
{
_content = window.Content;
var a = button.DataContext; // a == ViewModel
window.Content = button;
var b = button.DataContext; // b == MainWindow ??? why???
}
else
window.Content = _content;
});
}
}
在var a = ...设置断点,启动程序,点击按钮,执行步骤,观察button.DataContext以及Output窗口中的绑定错误。
【问题讨论】:
-
还在您设置 DC 的位置添加 UserControl1 代码,以及使用 DataTemplate 的原因和位置?
-
@AnjumSKhan,不需要设置
UserControl1.DataContext,因为数据模板。一切正常,直到您单击按钮。这是一个演示案例的重现,而不是真实的项目(必须使用数据模板)。 -
DataTemplate 是在 MainWindow 中使用的,所以它自然会从 MainWindow 中获取它的 DC。如果你在 UC 代码中设置了 UC 的 DC,那就不一样了。在您的 UC 中,不会有任何 DC,因为您没有设置它。一旦它成为 MainWindow 的一部分,它将获得它的 DC。
-
@AnjumSKhan,然后告诉我为什么
a == ViewModel?提问前可以先试一下代码吗? -
带有控件洞察力的 mvvm 复制品,它不是 mvvm 复制品,抱歉。
标签: wpf mvvm datacontext