- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在尝试学习 MVVM,但遇到了一个奇怪的问题。我有一个带有抽屉控件的主菜单,它出现并显示一个菜单:
在这个抽屉所在的主窗口中,我有一个 ContentControl
我在其中使用绑定(bind)设置其内容。
<ContentControl x:Name="MainWindowContentControl" Content="{Binding Path=WindowContent}"/>
此窗口的绑定(bind)设置为 View 模型。
<Window.DataContext>
<viewmodels:MainWindowViewModel/>
</Window.DataContext>
这是 ViewModel:
MainWindowViewModel.cs
public class MainWindowViewModel: ViewModelBase
{
private object _content;
public object WindowContent
{
get { return _content; }
set
{
_content = value;
RaisePropertyChanged(nameof(WindowContent));
}
}
public ICommand SetWindowContent { get; set; }
public MainWindowViewModel()
{
SetWindowContent = new ChangeWindowContentCommand(this);
}
}
到目前为止,一切正常。因此,例如,如果我单击“恢复操作”,我会得到:
在“RecoveryOperationsView.xaml”(这是一个 UserControl
)中,我也像这样从上面引用了 View 模型..
<UserControl.DataContext>
<viewmodels:MainWindowViewModel/>
</UserControl.DataContext>
并有一个按钮来调用命令来更改 ContentControl
的内容属性从主窗口..
<Button Grid.Row="2" Content="Restore Database" Width="150" Style="{StaticResource MaterialDesignFlatButton}" Command="{Binding SetWindowContent}" CommandParameter="DatabaseRecovery" >
在我处理命令的类中,我使用 switch 语句根据传递的参数更改内容
ChangeWindowContentCommand.cs
public class ChangeWindowContentCommand : ICommand
{
private MainWindowViewModel viewModel;
public ChangeWindowContentCommand(MainWindowViewModel vm)
{
this.viewModel = vm;
}
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
switch (parameter)
{
case "Home":
viewModel.WindowContent = new HomeView();
break;
case "RecoveryOps":
viewModel.WindowContent = new RecoveryOperationsView();
break;
case "DatabaseRecovery":
viewModel.WindowContent = new DatabaseRestoreView();
break;
}
}
}
然而,这就是我迷路的地方......如果我在这个新窗口中单击某些内容,说“恢复数据库”并使用断点检查它,我可以看到属性正在更改但实际 ContentControl
内容属性不会更改为新的 UserControl
我做了...我可以更改抽屉中的任何内容,但是如果我尝试单击 ContentControl
的托管内容中的按钮没有什么改变。我错过了什么?
最佳答案
如果没有对您的项目进行测试,很难 100% 确定,但我相当有信心至少有一个问题是您的 UserControl
和 MainWindow
使用 MainWindowViewModel
的不同实例。您不需要为用户控件实例化 VM,因为它将从 MainWindow
继承 DataContext
。它在 WPF 中的工作方式是,如果任何给定的 UIElement
没有显式分配了 DataContext
,它将从第一个元素向上继承它确实分配了一个逻辑树。
所以,只要删除这段代码,它至少应该能解决那个问题。
<UserControl.DataContext>
<viewmodels:MainWindowViewModel/>
</UserControl.DataContext>
由于您正在学习 WPF,我觉得有义务提供一些其他技巧。即使您使用的是 ViewModel,您仍然通过创建非常具体的 ICommand
实现并通过 ViewModel 分配 UI 元素来混合 UI 和逻辑。这打破了 MVVM 模式。我知道 MVVM 需要一点时间来理解,但是一旦你理解了,它就非常易于使用和维护。
为了解决您的问题,我建议为您的每个用户控件创建 View 模型。请看this answer ,我在其中详细介绍了实现。
要切换不同的 View ,您有几个选项。您可以使用 TabControl
,或者如果您想使用命令,您可以将单个 ContentControl
绑定(bind)到 MainWindowViewModel
的属性是 ViewModelBase
类型。我们称它为 CurrentViewModel
。然后当命令触发时,您将所需用户控件的 View 模型分配给该绑定(bind)属性。您还需要利用 implicit data templates .基本思想是为每个用户控制 VM 类型创建一个模板,它只包含一个 View 实例。当您将用户控件 VM 分配给 CurrentViewModel
属性时,绑定(bind)将找到那些数据模板并呈现用户控件。例如:
<Window.Resources>
<DataTemplate DataType = "{x:Type viewmodels:RecoveryOperationsViewModel}">
<views:RecoveryOperationsView/>
</DataTemplate>
<!-- Now add a template for each of the views-->
</Window.Resources>
<ContentControl x:Name="MainWindowContentControl" Content="{Binding CurrentViewModel}"/>
看看这种方法如何使 UI 和逻辑保持一定距离?
最后,考虑创建一个非常通用的 ICommand
实现,以在您的所有 ViewModel 中使用,而不是许多特定的实现。我认为大多数 WPF 程序员或多或少都有这个确切的 RelayCommand implementation在他们的武器库中。
关于c# - ContentControl 内容属性不随托管内容而改变,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53383868/
在我们的 VSTO Word 2010 插件中,我们试图在给定的其他 ContentControl 之后插入一个 RichTextControl。我们试过这个: public ContentC
ContentControl.Template 和 ContentControl.ContentTemplate 有什么区别?我什么时候使用哪个? 例如,我可以在 WPF 的 xaml 文件中编写:
我有一个 ViewModel,它表示多个选项并实现 IDataErrorInfo。仅当至少选择了这些选项之一时,此 ViewModel 才有效。它绑定(bind)到 ContentControl。 D
我已经用这个把头撞在墙上有一段时间了。 我有一个从 ContentControl 派生的自定义控件 - 它完美地工作,除了它不会以声明方式或以编程方式调整大小以适应其父级。 自定义控件以(最终)内容呈
以下代码位于 MEF MVVM 桌面应用程序中。 Shell 已经构建,但正在初始化一个模块。 模块想要将文本添加到 Shell 中的 ContentControl,但以下代码不会导致在 Shell
我正在尝试创建自定义工具提示控件。该控件继承自ToolTip类。我的自定义工具提示将有一个标题和一个内容区域。内容可以是普通文本或任何其他内容(图像、richtextbox 等)。以下是自定义工具提示
我有一个自定义 WPF 控件。它有一个嵌套的 ContentControl,它绑定(bind)到模板的 Content 属性,因此它可以将任何对象设置为其内容。 如果内容是原始字符串,我想将以下样式应
我正在尝试构建一个控件,它根据传入的类型有选择地显示不同的内容,但由于某种原因,我最终什么也没显示。 我在这里缺少一些基本的东西吗? (此代码已从我的实际生产应用程序中大量剥离,但表现出相同的行为)
我有一个自定义 ContentControl,它具有固定的 XAML 布局,如 UserControl(而不是通常应用的通用模板)。 以前这个布局没有额外的标记,所以它的字面意思是: 这很好用。
我整晚都在为这个问题苦思冥想。我想要做的就是拥有一个内容控件,它可以根据 ViewModel 中的 bool 值在显示两个不同按钮之间切换。 基本上我有一个任务在后台运行,带有一个取消按钮。一旦你点击
我正在为 Word 2007 开发应用程序级加载项插件。不幸的是,我在设置动态添加的内容时遇到了一个小问题: 我已经创建了内容控件,并使用以下代码更改了它的样式: PlainTextContentCo
我最近偶然发现了以下问题:在我的 WPF 应用程序中,我实现了一个小设计器,您可以在其中将元素放在 Canvas 上,移动、缩放和旋转它们。 在网上搜索时,我找到了 following solutio
我正在尝试学习 MVVM,但遇到了一个奇怪的问题。我有一个带有抽屉控件的主菜单,它出现并显示一个菜单: 在这个抽屉所在的主窗口中,我有一个 ContentControl我在其中使用绑定(bind)设置
我正在尝试拥有一个绑定(bind)到 View 的 MainWindow。我在代码中更改了该 View 并希望它在主窗口中更新,但是这并没有发生。 我的 XAML 中有这段代码 然后我通
我试图创建一些图表图像,但从未在屏幕上显示这些图表。我已经在这方面工作了很长一段时间并尝试了很多不同的事情,但似乎没有任何效果。如果我首先在窗口中显示图表,则代码可以完美运行,但如果我不在窗口中显示它
谁能告诉我为什么这会使我的应用程序崩溃?我不知道为什么似乎有一些无休止的递归。我得到了这个异常(exception) Logical tree depth exceeded while travers
我不知道这里发生了什么。当我直接绑定(bind)到 TextBox 时,可以编辑值,但我想绑定(bind)到 ContentControl 中。 为什么 ContentControl 不更新 View
我想禁用我的一个元素的 EntrenceThemeAnimation。我有一个网格,将此动画设置为其所有子项(我认为这是页面的默认设置)。是否可以为该网格的子级 ContentControl 禁用此动
为什么我无法在设计时解析 ContentControl ContentTemplateSelector? (在运行时有效) Designer(VS2010)显示异常: System.Reflectio
我想创建内部有一个“子”控件的自定义 WPF 控件。子类化 ContentControl 或 UserControl 可行,但有一个缺陷:这些控件在设计器模式下不起作用。 “不起作用”是指这种情况:假
我是一名优秀的程序员,十分优秀!