UserControl 未在 WPF ContentControl 中呈现

问题描述 投票:0回答:1

我是 WPF 和 MVVM 新手。我花了两天时间浏览了一堆关于这个主题的问答,但我还没有成功地让它发挥作用。这不可避免地意味着我忽略了一些愚蠢的事情。

我尝试使用

DataTemplate
ContentControl
在用户更改
DataGrid
控件中的选项卡时在内容
Fluent:Ribbon
之间切换。我想重用这些视图,因为其中包含的
DataGrid
的填充成本可能很高。

我有这些视图/视图模型:

  • MainWindow.xaml
    /
    MainWindowViewModel.cs
    - 主应用程序窗口由
    Fluent:RibbonWindow
    Fluent:Ribbon
    Fluent:StatusBar
    控件组成(为了清楚起见,在下面的代码片段中删除了其中一些控件)。此类包含用于跟踪“当前内容”(
    CurrentViewModel
    ) 的成员属性和用于当用户单击
    Fluent:Ribbon
    中的按钮时进行命令处理的成员属性。其他视图模型在此类中实例化为私有成员。
  • ProviderView.xaml
    /
    ProviderViewModel.cs
    - 显示“提供商”列表(就本文而言,只是一个抽象概念)。该视图包含一个
    UserControl
    ,其中包含一个
    DataGrid
    控件。
    DataGrid
    绑定到
    Providers
    实例内的公共
    ProviderViewModel
    属性(Provider 对象的列表),这是
    MainWindowViewModel
    的公共属性。

当我运行应用程序时,在设计器中也很明显,

ContentControl
只包含一个字符串
ViewModel.ProviderViewModel
,好像它不知道如何处理该控件,或者我没有正确地树化它。

enter image description here

MainWindow.xaml

<Fluent:RibbonWindow x:Class="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:vm="clr-namespace:ViewModel"
                     xmlns:local="clr-namespace:MyProgram"
                     xmlns:Fluent="urn:fluent-ribbon"
                     mc:Ignorable="d"
                     Width="800" 
                     Height="600"
                     Name="MainRibbonWindow"
                     Icon="{DynamicResource logo}">
    <Fluent:RibbonWindow.Resources>
        <DataTemplate x:Key="g_ProviderViewModel" DataType="{x:Type vm:ProviderViewModel}">
            <local:ProviderView/>
        </DataTemplate>
    </Fluent:RibbonWindow.Resources>
    <Fluent:RibbonWindow.DataContext><vm:MainWindowViewModel/></Fluent:RibbonWindow.DataContext>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <Fluent:Ribbon VerticalAlignment="Top"
                       IsDisplayOptionsButtonVisible="False"
                       Name="MainWindowRibbon"
                       SelectedTabChanged="MainWindowRibbon_SelectedTabChanged">

            <!--Tabs-->
            <Fluent:RibbonTabItem Header="Providers" Name="ProvidersTab">
                <Fluent:RibbonGroupBox Header="Options" Width="120">
                    <Fluent:Button Header="Refresh"
                                   Icon="{DynamicResource refresh}"
                                   Command="{Binding LoadProvidersCommand}"/>
                </Fluent:RibbonGroupBox>
            </Fluent:RibbonTabItem>            
        </Fluent:Ribbon>
        <StackPanel HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.Row="1">
            <ContentControl Content="{Binding CurrentViewModel}"/>
        </StackPanel>
    </Grid>
</Fluent:RibbonWindow>

MainWindowViewModel.cs


namespace MyProgram.ViewModel
{
    class MainWindowViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private ViewModelBase _CurrentViewModel;
        public ViewModelBase CurrentViewModel
        {
            get => _CurrentViewModel;
            set
            {
                _CurrentViewModel = value;
                OnPropertyChanged("CurrentViewModel");
            }
        }

        public ProviderViewModel m_ProviderViewModel = new ProviderViewModel();
        private ProviderManifestViewModel m_ProviderManifestViewModel = new ProviderManifestViewModel();

        private ICommand _loadProvidersCommand;
        public ICommand LoadProvidersCommand
        {
            get
            {
                return _loadProvidersCommand ?? (_loadProvidersCommand = new AsyncRelayCommand(Command_LoadProviders, GlobalUiCanExecute));
            }
        }

        private AsyncRelayCommand<Guid> _loadProviderCommand;
        public AsyncRelayCommand<Guid> LoadProviderCommand
        {
            get
            {
                return _loadProviderCommand ?? (_loadProviderCommand = new AsyncRelayCommand<Guid>(Command_LoadProvider));
            }
        }
        #endregion

        public MainWindowViewModel()
        {
            CurrentViewModel = m_ProviderViewModel;
        }

        protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        public void ShowProviderViewModel()
        {
            CurrentViewModel = m_ProviderViewModel;
        }

        private async Task Command_LoadProviders()
        {
            g_UiBusy = true;
            CurrentViewModel = m_ProviderViewModel;
            await m_ProviderViewModel.LoadProviders();
            g_UiBusy = false;
        }

        private async Task<MyProvider?> Command_LoadProvider(Guid Id)
        {
            if (!GlobalUiCanExecute())
            {
                return null;
            }
            g_UiBusy = true;
            var provider = await m_ProviderViewModel.LoadProvider(Id);
            g_UiBusy = false;
            return provider;
        }
    }
}

ProviderView.xaml

<UserControl x:Class="MyProgram.ProviderView"
             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:MyProgram.ViewModel"
             xmlns:Fluent="urn:fluent-ribbon"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800"
             Name="ProviderViewControl">
    <UserControl.DataContext><local:MainWindowViewModel/></UserControl.DataContext>
    <Grid Name="ProvidersGrid">
        <DataGrid Name="ProvidersDataGrid"
                  IsReadOnly="true"
                  AutoGenerateColumns="false"
                  ItemsSource="{Binding m_ProviderViewModel.Providers}">
            <DataGrid.Columns>
                <DataGridTextColumn Header="ID" Binding="{Binding Id}"/>
                <DataGridTextColumn Header="Name" Binding="{Binding Name}" />
                <DataGridTextColumn Header="Source" Binding="{Binding Source}" />
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</UserControl>

ProviderViewModel.cs


namespace MyProgram.ViewModel
{
    class ProviderViewModel : ViewModelBase
    {
        private ObservableCollection<MyProvider> _providers;
        public ObservableCollection<MyProvider> Providers
        {
            get => _providers;
            set
            {
                _providers = value;
                OnPropertyChanged("Providers");
            }
        }

        public ProviderViewModel()
        {
            _providers = new ObservableCollection<MyProvider>();
        }

        public async Task LoadProviders()
        {
            var providers = await ProviderLoader.GetProviders();
            if (providers == null)
            {
                return;
            }
            providers.ForEach(f => Providers.Add(f));
        }
    }
}

c# wpf xaml mvvm
1个回答
0
投票

试试这个。 更换:

<StackPanel HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.Row="1">
    <ContentControl Content="{Binding CurrentViewModel}"/>
</StackPanel>

与:

<StackPanel HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.Row="1">
    <local:ProviderView DataContext="{Binding CurrentViewModel}"/>
</StackPanel>

从 ProviderView.xaml 中

删除

<UserControl.DataContext><local:MainWindowViewModel/></UserControl.DataContext>
© www.soinside.com 2019 - 2024. All rights reserved.