嵌套用户控件 wpf 中定义的访问命令

access command defined in nested user controls wpf

我有一个 MainWindow 来自 Window class。 window 有一个 ContentControl 用于在其中托管用户 UserControl objects。我正在尝试创建一个按钮,该按钮将访问在嵌套 UserControl 中定义的 Command。唯一的技巧是我的用户控件实际上也嵌套了更多的用户控件,我实际上是在使用 grand-child 命令,而不仅仅是 child。像这样:

主要Window:

<metro:MetroWindow  x:Class="GrimshawRibbon.Revit.Wpf.MainWindow"
                    x:Name="win"
                    xmlns:metro="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
                    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:pmModel="clr-namespace:GrimshawRibbon.Revit.Management.ParametersManagerWPF.ViewModel"
                    xmlns:pmLocal="clr-namespace:GrimshawRibbon.Revit.Management.ParametersManagerWPF"
                    xmlns:local="clr-namespace:GrimshawRibbon.Revit.Wpf"
                    mc:Ignorable="d" Height="400" Width="600" ResizeMode="CanResizeWithGrip" 
                    Title="{Binding WindowTitle, Mode=OneWay, FallbackValue='GrimshawDT'}" BorderBrush="{DynamicResource AccentColorBrush}" BorderThickness="1"
                    WindowStartupLocation="CenterScreen" WindowTransitionsEnabled="False">
    <metro:MetroWindow.Resources>
        <ResourceDictionary>
            <DataTemplate DataType="{x:Type pmModel:pmViewModel}">
                <pmLocal:pmMain />
            </DataTemplate>
        </ResourceDictionary>
    </metro:MetroWindow.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height = "100" />
            <RowDefinition/>
        </Grid.RowDefinitions>

        <ContentControl x:Name="MainContentControl" Content="{Binding CurrentPageViewModel}" Margin="10" Grid.Row="1"/>
        <Button x:Name="btnOK" Content="OK" Margin="0,0,211,10" HorizontalAlignment="Right" Width="75" Height="36" VerticalAlignment="Bottom" Command="{Binding pmModel:pmViewModel.ApplyCommand, Mode=OneWay}" Grid.Row="1" metro:ButtonHelper.CornerRadius="0" metro:ControlsHelper.ContentCharacterCasing="Normal" BorderThickness="1" metro:ButtonHelper.PreserveTextCase="True"/>
    </Grid>
</metro:MetroWindow>

嵌套在 Main 中的控件Window:

<UserControl x:Class="GrimshawRibbon.Revit.Management.ParametersManagerWPF.pmMain"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
             xmlns:ignore="http://www.ignore.com"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:GrimshawRibbon.Revit.Management.ParametersManagerWPF" 
             xmlns:viewModel="clr-namespace:GrimshawRibbon.Revit.Management.ParametersManagerWPF.ViewModel"
             xmlns:Custom="http://metro.mahapps.com/winfx/xaml/controls"
             mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="600">
    <UserControl.Resources>
        <ResourceDictionary>
            <DataTemplate DataType="{x:Type viewModel:pmSetParamToValueViewModel}">
                <local:pmSetParamToValueView />
            </DataTemplate>
            <DataTemplate DataType="{x:Type viewModel:pmCopyParamToParamViewModel}">
                <local:pmCopyParamToParamView />
            </DataTemplate>
            <DataTemplate DataType="{x:Type viewModel:pmCopyParamToParamSliceViewModel}">
                <local:pmCopyParamToParamSliceView />
            </DataTemplate>
            <DataTemplate DataType="{x:Type viewModel:pmCombineTwoSlicesViewModel}">
                <local:pmCombineTwoSlicesView />
            </DataTemplate>
        </ResourceDictionary>
    </UserControl.Resources>
    <Grid>
        <ComboBox x:Name="cbType" Margin="0,26,0,0" Height="22" VerticalAlignment="Top" ItemsSource="{Binding PageNames}" SelectedIndex="{Binding SelectedVMIndex}" Custom:TextBoxHelper.Watermark="Parameter Manager Functionality"/>
        <ContentControl x:Name="contentControl" Content="{Binding CurrentPageViewModel}" Margin="0,57,0,0"/>
        <Label x:Name="label" Content="Select Functionality:" HorizontalAlignment="Left" VerticalAlignment="Top" FontWeight="Bold"/>
    </Grid>
</UserControl>

这又具有更多像这样的嵌套控件:

<UserControl x:Class="GrimshawRibbon.Revit.Management.ParametersManagerWPF.pmSetParamToValueView"
             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:GrimshawRibbon.Revit.Management.ParametersManagerWPF"
             xmlns:Custom="http://metro.mahapps.com/winfx/xaml/controls" 
             mc:Ignorable="d" d:DesignWidth="600" d:DesignHeight="200">
    <Grid>
        <ComboBox x:Name="cbCategories" HorizontalAlignment="Left" VerticalAlignment="Top" Width="180" ItemsSource="{Binding Categories}" DisplayMemberPath="Name" SelectedItem="{Binding SelectedCategory}" Custom:TextBoxHelper.Watermark="Category" Margin="0,26,0,0"/>
        <ComboBox x:Name="cbSourceParam" HorizontalAlignment="Left" Margin="0,57,0,0" Width="180" Height="22" VerticalAlignment="Top" ItemsSource="{Binding Parameters}" DisplayMemberPath="Name" SelectedItem="{Binding SelectedParameter}" Custom:TextBoxHelper.Watermark="Source Parameter"/>
        <TextBox x:Name="tbParamValue" Margin="185,57,0,0" Height="23" VerticalAlignment="Top" Text="{Binding Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Custom:TextBoxHelper.Watermark="Parameter Value"/>
        <Label x:Name="label" Content="Define Parameters:" HorizontalAlignment="Left" VerticalAlignment="Top" FontWeight="Bold"/>
    </Grid>
</UserControl>

现在,当在主 window 中点击确定按钮时,我希望第二个嵌套控件执行 ApplyCommand。这是我的第二个用户控件的视图模型:

namespace GrimshawRibbon.Revit.Management.ParametersManagerWPF.ViewModel
{
    public class pmSetParamToValueViewModel : ViewModelBase
    {
        public pmModel model;
        public ObservableCollection<CategoryWrapper> Categories { get; private set; }
        public RelayCommand ApplyCommand { get; private set; }

        public pmSetParamToValueViewModel(Document doc)
        {
            this.model = new pmModel(doc);
            this.Categories = model.CollectCategories();
            SelectedCategory = Categories[0];
            this.ApplyCommand = new RelayCommand(this.Apply);
        }

        // logic for apply button
        private void Apply()
        {
            model.Apply(SelectedCategory.ID, SelectedParameter, null, null, Value, null, null, null, "Apply");
        }

        // logic for storing parameter value
        private string _value;
        public string Value
        {
            get { return _value; }
            set
            {
                if (_value == value) return;

                _value = value;
                RaisePropertyChanged(() => Value);
            }
        }

        // storage for source parameters
        private ObservableCollection<ParameterWrapper> _parameters;
        public ObservableCollection<ParameterWrapper> Parameters
        {
            get { return _parameters; }
            set
            {
                if (_parameters == value) return;

                _parameters = value;
                RaisePropertyChanged(() => Parameters);
                if (Parameters.Count > 0)
                {
                    SelectedParameter = Parameters[0];
                }
            }
        }

        // logic for selected category
        private CategoryWrapper _selectedCategory;
        public CategoryWrapper SelectedCategory
        {
            get { return _selectedCategory; }
            set
            {
                if (_selectedCategory == value) return;

                _selectedCategory = value;
                RaisePropertyChanged(() => SelectedCategory);
                Parameters = model.CollectParameters(SelectedCategory.ID, new string[] { "String", "Double", "Integer" });
            }
        }

        // logic for selected source parameter
        private ParameterWrapper _selectedParameter;
        public ParameterWrapper SelectedParameter
        {
            get { return _selectedParameter; }
            set
            {
                if (_selectedParameter == value) return;

                _selectedParameter = value;
                RaisePropertyChanged(() => SelectedParameter);
            }
        }
    }
}

谁能告诉我如何在 Main Window 中设置确定按钮,以便能够访问在嵌套用户控件中定义的命令。或者有没有办法设置一个确定按钮来检索给定嵌套用户控件的当前状态,以便我可以检索它们的属性并将它们用作我的 ApplyCommand 的参数?

干杯!

您似乎已经在主视图模型中引用了子视图模型,所以我相信这应该可行:

<Button x:Name="btnOK" Content="OK" Margin="0,0,211,10" HorizontalAlignment="Right" Width="75" Height="36" VerticalAlignment="Bottom" Command="{Binding CurrentPageViewModel.CurrentPageViewModel.ApplyCommand}" Grid.Row="1" metro:ButtonHelper.CornerRadius="0" metro:ControlsHelper.ContentCharacterCasing="Normal" BorderThickness="1" metro:ButtonHelper.PreserveTextCase="True"/>