C# 动态内容的WPF ContentControl绑定无法正常工作

C# 动态内容的WPF ContentControl绑定无法正常工作,c#,wpf,xaml,mvvm,C#,Wpf,Xaml,Mvvm,再次,我为任何错误提前道歉,英语不是我的母语。 我正在制作一个MVVM应用程序,我想在主窗口中使用ContentControl动态更改视图,下面是代码中需要理解的部分: 第一,意见: MainWindow.xaml <Window x:Class="Vernam.MainWindow" x:Name="MainWindowID" xmlns="http://schemas.microsoft.com/winf

再次,我为任何错误提前道歉,英语不是我的母语。 我正在制作一个MVVM应用程序,我想在主窗口中使用ContentControl动态更改视图,下面是代码中需要理解的部分:

第一,意见: MainWindow.xaml

<Window x:Class="Vernam.MainWindow"
        x:Name="MainWindowID"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Vernam"
        xmlns:viewModel="clr-namespace:Vernam.ViewModels"
        mc:Ignorable="d"
        Height="600"
        Width="900"
        ...>

    <Window.Resources>
        <viewModel:MainViewModel x:Key="vm"></viewModel:MainViewModel>
    </Window.Resources>
                  ...
          <Grid>
            <Grid Grid.Row="0">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="150"></ColumnDefinition>
                    <ColumnDefinition Width="40"></ColumnDefinition>
                    <ColumnDefinition Width="454"></ColumnDefinition>
                    <ColumnDefinition></ColumnDefinition>
                </Grid.ColumnDefinitions>

                ...
                <StackPanel Grid.Column="2" Orientation="Horizontal"
                            DataContext="{Binding Source={StaticResource vm}}">
                    <RadioButton x:Name="CorrRadioButton"
                        Content="Correspondences"
                        Width="176"
                        Foreground="White"
                        FontSize="18"
                        Style="{StaticResource HeadButtonTheme}"
                        GroupName="Head"
                        IsChecked="True"
                        Command="{Binding Path=CorrCommand}"/>
                    <RadioButton x:Name="ProfileRadioButton"
                        Content="Profile"
                        Width="89"
                        Foreground="White"
                        FontSize="18"
                        Style="{StaticResource HeadButtonTheme}"
                        GroupName="Head"
                        Command="{Binding Path=ProfileCommand}"/>
                </StackPanel>

               ...

            </Grid>
            <ContentControl Grid.Row="1"
                            Content="{Binding CurrentView}"/>
        </Grid>
    </Border>
    </Window>

我希望在主窗口中显示的两个视图:

通信视图.xaml

<UserControl x:Class="Vernam.Views.CorrespondensesView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:Vernam.Views"
             mc:Ignorable="d"
             Height="540"
             Width="900">
    <Grid Background="#035251">
        ...
    </Grid>
</UserControl>
ProfileView.xaml:

<UserControl x:Class="Vernam.Views.ProfileView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:Vernam.Views"
             mc:Ignorable="d" 
             Height="540"
             Width="900">
    <Grid Background="#035251">
        ...
    </Grid>
</UserControl>

这里是主窗口视图模型

namespace Vernam.ViewModels
{
    public class MainViewModel : ObservableObject
    {
        private RelayCommand corrCommand;
        private RelayCommand profileCommand;
        private object currentView;

        public CorrespondensesViewModel CorrVM { get; set; }
        public ProfileViewModel ProfileVM { get; set; }

        public object CurrentView
        {
            get { return currentView; }
            set
            {
                currentView = value;
                this.OnPropertyChanged("CurrentView");
            }
        }
        public RelayCommand CorrCommand
        {
            get
            {
                return corrCommand ??
                    (corrCommand = new RelayCommand(obj =>
                    {
                        CurrentView = CorrVM;
                    }));
            }
        }

        public RelayCommand ProfileCommand
        {
            get
            {
                return profileCommand ??
                    (profileCommand = new RelayCommand(obj =>
                    {
                        CurrentView = ProfileVM;
                    }));
            }
        }
        public MainViewModel()
        {
            CorrVM = new CorrespondensesViewModel();
            ProfileVM = new ProfileViewModel();
            
            CurrentView = CorrVM;
        }
    }
}
对应的ViewModel和ProfileViewModel为空

最后是App.xaml

<Application x:Class="Vernam.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:Vernam"
             xmlns:viewModel="clr-namespace:Vernam.ViewModels"
             xmlns:view="clr-namespace:Vernam.Views"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <ResourceDictionary>
             ...
            <DataTemplate DataType="{x:Type viewModel:CorrespondensesViewModel}">
                <view:CorrespondensesView/>
            </DataTemplate>
            <DataTemplate DataType="{x:Type viewModel:ProfileViewModel}">
                <view:ProfileView/>
            </DataTemplate>
        </ResourceDictionary>
    </Application.Resources>
</Application>
然后我运行应用程序,我可以实际看到我在MainViewModel构造函数中分配给CurrentView的视图:

        public MainViewModel()
        {
            CorrVM = new CorrespondensesViewModel();
            ProfileVM = new ProfileViewModel();
            
            CurrentView = CorrVM;
        }
如果我将CorrVM或ProfileVM分配给CurrentView,我实际上会看到对应的视图或ProfileView,但我无法动态更改视图:

RadioButton命令绑定工作正常,每次单击相应按钮时都会重新分配CurrentView,但在MainWindow中看不到任何更改

 <ContentControl Grid.Row="1" Grid.Column="0"
                        Content="{Binding CurrentView}"  />
所以我认为问题出在装订上,你有什么办法解决它吗

UPD: 此属性的Get部分仅在初始化期间调用,因此问题肯定出在绑定上

public ObservableObject CurrentView
        {
            get { return currentView; }
            set
            {
                currentView = value;
                this.OnPropertyChanged("CurrentView");
            }
        }
尝试使用不同的绑定模式和更新触发器,但无效

<ContentControl Grid.Row="1"
                            Content="{Binding Path=CurrentView, UpdateSourceTrigger=PropertyChanged,  Mode=OneWay}"/>

尝试以下操作:

创建以下文件夹:

  • 模型
  • 主题
  • 看法
  • 视图模型

将下面的文件添加到相应的文件夹中(参见上图)

HeadButtonTheme.xaml(资源字典)

RelayCommand.cs(类)

对应视图.xaml(用户控件)

ProfileView.xaml(用户控件)

App.xaml

<Application x:Class="Vernam.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:Vernam"
             xmlns:viewModel="clr-namespace:Vernam.ViewModel"
             xmlns:view="clr-namespace:Vernam.View"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Theme\HeadButtonTheme.xaml" />
            </ResourceDictionary.MergedDictionaries>

            <DataTemplate DataType="{x:Type viewModel:CorrespondencesViewModel}">
                <view:CorrespondencesView />
            </DataTemplate>

            <DataTemplate DataType="{x:Type viewModel:ProfileViewModel}">
                <view:ProfileView />
            </DataTemplate>
                          
        </ResourceDictionary>
    </Application.Resources>
</Application>
<Window x:Class="Vernam.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Vernam"
        xmlns:viewModel="clr-namespace:Vernam.ViewModel"
        xmlns:view="clr-namespace:Vernam.View"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">

    <Window.Resources>
        <viewModel:MainViewModel x:Key="vm"></viewModel:MainViewModel>
    </Window.Resources>
    
    <Border Background="LightGray">
        <Grid DataContext="{Binding Source={StaticResource vm}}">

            <Grid.RowDefinitions>
                <RowDefinition Height="50" />
                <RowDefinition />
            </Grid.RowDefinitions>
            
            <Grid Grid.Row="0">

                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="350" />
                    <ColumnDefinition Width="350" />
                    <ColumnDefinition />
                </Grid.ColumnDefinitions>
                
                <StackPanel Orientation="Horizontal">
                    <RadioButton x:Name="CorrRadioButton"
                        Content="Correspondences"
                        Width="176"
                        Foreground="White"
                        FontSize="18"
                        Style="{StaticResource HeadButtonTheme}"
                        GroupName="Head"
                        IsChecked="True"
                        Command="{Binding CorrCommand}"/>

                    <RadioButton x:Name="ProfileRadioButton"
                        Content="Profile"
                        Width="89"
                        Foreground="White"
                        FontSize="18"
                        Style="{StaticResource HeadButtonTheme}"
                        GroupName="Head"
                        Command="{Binding ProfileCommand}"/>
                </StackPanel>
            </Grid>
            
            <ContentControl Grid.Row="1" Grid.Column="0"
                            Content="{Binding CurrentView}"  />
        </Grid>
    </Border>
</Window>


我相信这是因为您在主窗口中为单选按钮和内容视图使用了两种不同的视图模型实例

 <ContentControl Grid.Row="1" Grid.Column="0"
                        Content="{Binding CurrentView}"  />
这里使用窗口资源中的一个实例

 <StackPanel Grid.Column="2" Orientation="Horizontal"
                            DataContext="{Binding Source={StaticResource vm}}">

在这里,您将使用MainWindow数据上下文中的一个实例

 <ContentControl Grid.Row="1" Grid.Column="0"
                        Content="{Binding CurrentView}"  />


因此,修复非常简单,只需使用其中一个。

>WPF C#Professional Modern Flat UI教程。。。这就是我在自己的项目中使用的示例。我的代码实际上是一样的,我重新检查了好几次。它对我很有效。尝试删除“obj”文件夹(Vernam\obj)并重新生成。未成功。我更新了我的问题,如果不麻烦的话看看。我对WPF比较陌生,但我确实得到了我发布的教程,并成功地完成了工作。如果重命名文件/文件夹,我确实遇到了问题。我发现如果我用正确的名称创建一个新文件并复制相关代码,然后删除不需要的文件,效果会更好。
using System;
using System.Windows.Input;

namespace Vernam
{
    class RelayCommand : ICommand
    {
        private Action<object> _execute;
        private Func<object, bool> _canExecute;

        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested += value; }
        }

        public RelayCommand(Action<object> execute, Func<object, bool> canExecute = null)
        {
            _execute = execute;
            _canExecute = canExecute;
        }

        public bool CanExecute(object parameter)
        {
            return _canExecute == null || _canExecute(parameter);
        }

        public void Execute(object parameter)
        {
            _execute(parameter);
        }
    }
}
namespace Vernam.ViewModel
{
    class CorrespondencesViewModel
    {
    }
}
<UserControl x:Class="Vernam.View.CorrespondencesView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:Vernam.View"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">

    <Grid>
        <TextBlock Text="Correspondences" Foreground="Red"/>
    </Grid>
</UserControl>
namespace Vernam.ViewModel
{
    class ProfileViewModel
    {
    }
}
<UserControl x:Class="Vernam.View.ProfileView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:Vernam.View"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">

    <Grid>
        <TextBlock Text="Profile" Foreground="Red"/>
    </Grid>
</UserControl>
namespace Vernam.ViewModel
{
    class MainViewModel : ObservableObject
    {
        public RelayCommand CorrCommand { get; set; }
        public RelayCommand ProfileCommand { get; set; }

        public CorrespondencesViewModel CorrVM { get; set; }
        public ProfileViewModel ProfileVM { get; set; }

        private object currentView;

        public object CurrentView
        {
            get { return currentView; }
            set
            {
                currentView = value;
                OnPropertyChanged("CurrentView");
            }
        }

        public MainViewModel()
        {
            //create new instance
            CorrVM = new CorrespondencesViewModel();
            ProfileVM = new ProfileViewModel();

            CorrCommand = new RelayCommand(obj =>
            {
                CurrentView = CorrVM;
            });

            ProfileCommand = new RelayCommand(obj =>
            {
                CurrentView = ProfileVM;
            });


            //set default view
            CurrentView = CorrVM;
        }
    }
}
<Application x:Class="Vernam.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:Vernam"
             xmlns:viewModel="clr-namespace:Vernam.ViewModel"
             xmlns:view="clr-namespace:Vernam.View"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Theme\HeadButtonTheme.xaml" />
            </ResourceDictionary.MergedDictionaries>

            <DataTemplate DataType="{x:Type viewModel:CorrespondencesViewModel}">
                <view:CorrespondencesView />
            </DataTemplate>

            <DataTemplate DataType="{x:Type viewModel:ProfileViewModel}">
                <view:ProfileView />
            </DataTemplate>
                          
        </ResourceDictionary>
    </Application.Resources>
</Application>
<Window x:Class="Vernam.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Vernam"
        xmlns:viewModel="clr-namespace:Vernam.ViewModel"
        xmlns:view="clr-namespace:Vernam.View"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">

    <Window.Resources>
        <viewModel:MainViewModel x:Key="vm"></viewModel:MainViewModel>
    </Window.Resources>
    
    <Border Background="LightGray">
        <Grid DataContext="{Binding Source={StaticResource vm}}">

            <Grid.RowDefinitions>
                <RowDefinition Height="50" />
                <RowDefinition />
            </Grid.RowDefinitions>
            
            <Grid Grid.Row="0">

                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="350" />
                    <ColumnDefinition Width="350" />
                    <ColumnDefinition />
                </Grid.ColumnDefinitions>
                
                <StackPanel Orientation="Horizontal">
                    <RadioButton x:Name="CorrRadioButton"
                        Content="Correspondences"
                        Width="176"
                        Foreground="White"
                        FontSize="18"
                        Style="{StaticResource HeadButtonTheme}"
                        GroupName="Head"
                        IsChecked="True"
                        Command="{Binding CorrCommand}"/>

                    <RadioButton x:Name="ProfileRadioButton"
                        Content="Profile"
                        Width="89"
                        Foreground="White"
                        FontSize="18"
                        Style="{StaticResource HeadButtonTheme}"
                        GroupName="Head"
                        Command="{Binding ProfileCommand}"/>
                </StackPanel>
            </Grid>
            
            <ContentControl Grid.Row="1" Grid.Column="0"
                            Content="{Binding CurrentView}"  />
        </Grid>
    </Border>
</Window>
 <StackPanel Grid.Column="2" Orientation="Horizontal"
                            DataContext="{Binding Source={StaticResource vm}}">
 <ContentControl Grid.Row="1" Grid.Column="0"
                        Content="{Binding CurrentView}"  />