我想暂时放大(让它占用整个可用空间)窗口内容的一部分。
窗口布局非常复杂:许多嵌套面板,分割器,要放大的内容都是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
以及绑定错误。
答案 0 :(得分:1)
您必须尝试将DataTemplate
ContentTemplate
用作ContentControl
。由于ContentTemplate
在Content
上运行,因此它会使用Content
作为其DataContext
。而您的Content
包含ViewModel
。
一旦您的按钮不再是DataTemplate
的一部分,它就会使用MainWindow's
DataContext
。
没有看到您的评论,我假设您希望DataContext
UserControl
保持不变,即使您的UserControl
不属于DataTemplate
。
因此,使用DataContext
明确使用Button
XAML
RelativeSource
的简单集<Button Content="{Binding Data}" DataContext="{Binding vm1, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" />
。
示例,
DataContext
在代码中使用foreach ($arr1[0] as $key => $entry) {
$arr1[0][$key][$arr1[0][$key]["Str1"]] = $arr2[0][$entry["Str1"]];
}
并不是一个好主意。
答案 1 :(得分:1)
这里有一些一般的想法。
如果将对象(viewmodel)绑定到contentcontrol的Content属性,则wpf使用DataTemplate来可视化对象。如果您没有DataTemplate,您只需看到object.ToString()。 DataContext继承意味着DataContext继承到子元素。所以真正的用户控件将从父级继承DataContext。这是您在创建UserControl时在stackoverflow上找到的常见错误 - 它们通常会破坏DataContext继承并将DataContext设置为self或新的DataContext。