2017-02-10 77 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();} 我 –