2017-02-10 11 views
1

Windowクラスから派生したMainWindowがあります。そのウィンドウには、ユーザーUserControlをホストするために使用されるContentControlがあります。私はその中で定義されたCommandにアクセスするボタンを作成しようとしていますUserControl。唯一のトリックは、私のユーザーコントロールに実際に多くのユーザーコントロールがネストされていることです。実際には子供だけではなく、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> 

今、メインウィンドウでOKボタンが押されると、この2番目のネストされたコントロールに0123を実行させます。これは私の第二のユーザコントロールのビューモデルである:

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

あなたがメインのviewmodelで、すでに子の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

はい、これは素晴らしい作品。ありがとうございました。私はあなたに賞金を授与します。私はしかし、私が求めていることは、本当にやりたいことではないことを認識しました。私はいつも別のユーザーコントロールの中にネストされたユーザーコントロールを持つつもりはありません。ときには(たいていの場合)、私はただ1つのユーザーコントロールを持っています。両方の場合を処理するために、 'Binding CurrentPageViewModel.ApplyCommand'のようにそのボタンをバインドし、' ApplyCommand'と 'Apply'メソッドをメインのユーザコントロールの中に入れて、可能であればそこから移動したいと思います。 'ViewModel'のコードからネストされたコントロールにアクセスする方法はありますか? – konrad

+0

問題は、 'CurrentPageViewModel'が基本クラス' ViewModelBase'であり、その内部のメソッドにアクセスできないということです。現在のページはビューモデルのいずれかになる可能性があるので、そのメソッドにアクセスする前に、選択した特定のモデルにキャストする必要があります。 :-(私は自分のベースビューモデルを実装して、それに適用メソッドを追加して常に利用できるようにすることができます。 – konrad

+0

これはあなたのことを理解しているとは思えません。場合によっては、CurrentPageViewModel.ApplyCommandにボタンをバインドすることもできますが、この行に沿って何かを行うことができます。 if(this.CurrentPageViewModel!= null) { this.CurrentPageViewModel.ApplyCommand.Execute() 他} { this.Apply(); } –

関連する問題