2017-02-10 83 views
1

我已经从Window类派生的MainWindow。该窗口有一个ContentControl,用于托管用户UserControl中的对象。我正在尝试创建一个按钮,该按钮将访问在嵌套UserControl中定义的Command。唯一的窍门是,我的用户控件实际上嵌套了更多的用户控件,而我实际上是为了使用grand-child命令而不是仅仅是一个孩子。事情是这样的:访问命令WPF

主窗口:即嵌套到主窗口

<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> 

控制:

<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> 

现在,当在主窗口中点击确定按钮时,我想要第二个嵌套控件执行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); 
      } 
     } 
    } 
} 

谁能告诉我如何设置在主窗口中的OK按钮,能够访问嵌套的用户控件中定义的命令。还有一种方法可以设置OK按钮来检索给定嵌套用户控件的当前状态,以便我可以检索它们的属性并将它们用作我的ApplyCommand的参数?

干杯!

回答

1

看起来好像你已经在你的主视图模型对孩子的ViewModels引用,所以我认为这应该工作:

<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"/> 
+0

是的,这个伟大的工程。谢谢。我会奖赏你的赏金。然而,我意识到我所要求的并不是我真正想要做的。我并不总是有一个用户控件嵌套在另一个用户控件中。有时(大部分时间)我只有一个用户控件。为了处理这两种情况下我想结合这个按钮,像这样'绑定CurrentPageViewModel.ApplyCommand'然后把'ApplyCommand'和'Apply'方法的主要用户控件中,如果可能从那里走。有没有办法从'ViewModel'中的代码访问我的嵌套控件? – konrad

+0

问题是'CurrentPageViewModel'是一个基类'ViewModelBase',并且不允许我访问它里面的方法。由于当前页面可以是任何视图模型,我需要将其转换为选定的特定模型,然后才能访问其方法。 :-(我可以实现我自己的基本视图模型,并添加应用方法它,因此它总是可用的。那是很长的路要走? – konrad

+0

我不能肯定我明白了,所以道歉,如果这不工作,你的场景,但也许你可以按照你的建议将你的按钮绑定到CurrentPageViewModel.ApplyCommand,但是沿着这条线: 如果(this.CurrentPageViewModel!= null) {0127}这个当前页面模型.ApplyCommand.Execute() } 其他 { this.Apply();} 我 –