gpt4 book ai didi

c# - ContentControl 内容属性不随托管内容而改变

转载 作者:太空狗 更新时间:2023-10-29 23:28:28 24 4
gpt4 key购买 nike

我正在尝试学习 MVVM,但遇到了一个奇怪的问题。我有一个带有抽屉控件的主菜单,它出现并显示一个菜单: enter image description here

在这个抽屉所在的主窗口中,我有一个 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 enter image description here

在“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% 确定,但我相当有信心至少有一个问题是您的 UserControlMainWindow 使用 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/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com