2016-06-25 3 views
0

私はメインViewModelにObservableCollection of ViewModelsを持っています。私はビューを切り替えることができるので、バインディングは正常に動作しているようです。しかし、ObservableCollectionの要素でViewModelBaseのOnPropertyChangedメソッド(他の要素で機能する)を呼び出すと、ViewModelBaseのnull PropertyChanged値が返されます。私のメインのViewModelコンストラクタで子ViewModelプロパティのPropertyChanged値がnullです

はここに私のメインのコードスニペットですGBAのROMの読み込みで

public EditorViewModel() 
    { 
     base.DisplayName = Strings.EditorName; 

     _availableEditors = new ObservableCollection<ViewModelBase>(); 

     AvailableEditors.Add(new GBARomViewModel(646, 384)); 
     AvailableEditors.Add(new MonsterViewModel(800, 500)); 

     CurrentEditor = _availableEditors[0]; 
    } 

、ViewModelにとモデルプロパティが更新されます。

void RequestOpenRom() 
    { 
     OpenFileDialog dlg = new OpenFileDialog(); 
     dlg.DefaultExt = ".gba"; 
     dlg.Filter = "GBA ROM (.gba)|*.gba|All files (*.*)|*.*"; 
     dlg.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); 

     Nullable<bool> result = dlg.ShowDialog(); 

     if (result == true) 
     { 
      if(CurrentEditor is GBARomViewModel) 
      { 
       (CurrentEditor as GBARomViewModel).ReadRom(dlg.FileName); 
      }    
     } 
    } 

で私のメインビュー: TabControlのバリエーション(ビューの切り替えとビューの状態を表示する保護)。 GBARomViewModel

<controls:TabControlEx ItemsSource="{Binding AvailableEditors}" 
     SelectedItem="{Binding CurrentEditor}" 
     Style="{StaticResource BlankTabControlTemplate}" 
     MinWidth="{Binding CurrentEditorWidth}" 
     MinHeight="{Binding CurrentEditorHeight}" 
     MaxWidth="{Binding CurrentEditorWidth}" 
     MaxHeight="{Binding CurrentEditorHeight}" 
     Width="{Binding CurrentEditorWidth}" 
     Height="{Binding CurrentEditorHeight}" 
     HorizontalAlignment="Left" 
     VerticalAlignment="Top"> 
     <controls:TabControlEx.Resources> 
      <DataTemplate DataType="{x:Type vm:GBARomViewModel}"> 
       <vw:GBARomView /> 
      </DataTemplate> 
      <DataTemplate DataType="{x:Type vm:MonsterViewModel}"> 
       <vw:MonsterView /> 
      </DataTemplate> 
     </controls:TabControlEx.Resources> 
    </controls:TabControlEx> 

(子ViewModelに、AvailableEditorsの要素)

public String CRC32 
    { 
     get 
     { 
      return _rom.CRC32; 
     } 
     set 
     { 
      if (value.Equals(_rom.CRC32)) 
      { 
       return; 
      } 

      _rom.CRC32 = value; 
      OnPropertyChanged("CRC32"); 
     } 
    } 

プロパティは、子ビュー
に結合が今、これはそう、私は後にもそのコードを出してあげるのUserControlです。起動時のその他のプロパティ(LabelWidthやLabelValueなど) XAMLのTextBoxValueに既定値を与えることもできます。

<StackPanel VerticalAlignment="Bottom" HorizontalAlignment="Left" Margin="10, 0, 0, 10" Width="300"> 
     <dlb:DefaultLabelBox LabelWidth="82" TextBoxWidth="100" HorizontalAlignment="Left" LabelValue="{x:Static p:Strings.RomTitle}" TextBoxValue="{Binding Title}" /> 
     <dlb:DefaultLabelBox LabelWidth="82" TextBoxWidth="100" HorizontalAlignment="Left" LabelValue="{x:Static p:Strings.RomGameCode}" TextBoxValue="{Binding GameCode}" /> 
     <dlb:DefaultLabelBox LabelWidth="82" TextBoxWidth="100" HorizontalAlignment="Left" LabelValue="{x:Static p:Strings.RomRomSize}" TextBoxValue="{Binding RomSize}" /> 
     <dlb:DefaultLabelBox LabelWidth="82" TextBoxWidth="100" HorizontalAlignment="Left" LabelValue="{x:Static p:Strings.RomCRC32}" TextBoxValue="{Binding CRC32}" /> 
     <dlb:DefaultLabelBox LabelWidth="82" TextBoxWidth="200" HorizontalAlignment="Left" LabelValue="{x:Static p:Strings.RomMD5Checksum}" TextBoxValue="{Binding MD5Checksum}"/> 
    </StackPanel> 

DefaultLabelBox.cs

<UserControl x:Name="uc"> 
    <StackPanel> 
     <TextBlock Text="{Binding Path=LabelValue, ElementName=uc}" 
      Width="{Binding Path=LabelWidth, ElementName=uc}"/> 
     <Label Content="{Binding Path=TextBoxValue, Mode=OneWay, ElementName=uc}" 
     Width="{Binding Path=TextBoxWidth, ElementName=uc}"/> 
    </StackPanel> 
</UserControl> 

DefaultLabelBox.xaml.cs

public string TextBoxValue 
    { 
     get { 
      return (string)GetValue(TextBoxValueProperty); 
     } 
     set { 
      SetValue(TextBoxValueProperty, value); 
     } 
    } 

    public static readonly DependencyProperty TextBoxValueProperty = 
     DependencyProperty.Register("TextBoxValue", typeof(string), typeof(DefaultLabelBox), new PropertyMetadata(default(string))); 

コントロールテンプレート

<Style TargetType="dlb:DefaultLabelBox"> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="dlb:DefaultLabelBox"> 
       <StackPanel Orientation="Horizontal"> 
        <TextBlock Text="{Binding LabelValue, RelativeSource={RelativeSource TemplatedParent}}" 
           MinWidth="20" 
           Width="{Binding LabelWidth, RelativeSource={RelativeSource TemplatedParent}}" 
           VerticalAlignment="Center" 
           FontFamily="Mangal" 
           Height="20" 
           FontSize="13"/> 
        <Label Content="{Binding TextBoxValue, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" 
          BorderBrush="{StaticResource DefaultLabelBoxBorderBrush}" 
          BorderThickness="1" 
          Padding="1,1,1,1" 
          Background="{StaticResource DefaultLabelBoxBackgroundBrush}" 
          Foreground="{StaticResource DefaultLabelBoxForeground}" 
           MinWidth="60" 
           Height="20" 
           VerticalAlignment="Center" 
           FontFamily="Mangal" 
           Width="{Binding TextBoxWidth, RelativeSource={RelativeSource TemplatedParent}}" 
           FontSize="13"/> 
       </StackPanel> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

私はいくつかのことを試みましたが、MVVMに新しくなりました。私にはバインディングのDataContextの問題があるかどうかわかりません。どんな助けもありがとう。

編集:私は忘れてしまったControlTemplateを追加するだけでなく、私のための解決策を説明するためにいくつかのコードを変更しました。私はMode = OneWayがUserControlとControlTemplateでは必須であるかどうかはわかりませんが、現在はそのまま動作していますのでそのまま残しています。

答えて

1

<dlb:DefaultLabelBox ... TextBoxValue="{Binding CRC32, Mode=TwoWay}" /> 

仕事のようバインディングを行うために、DefaultLabelBox(これはところでです。ユーザーコントロールは、明示的にDataContextを設定してはならない理由)親コントロールからのDataContextを継承する必要があります。

ただし、UserControlのXAML内の "内部"バインディングでは、明示的に指定されたSourceまたはRelativeSourceまたはElementNameが必要です。

そこで彼らは、(例えば)次のようになります。

<UserControl ... x:Name="uc"> 
    <StackPanel> 
     <TextBlock 
      Text="{Binding Path=LabelValue, ElementName=uc}" 
      Width="{Binding Path=LabelWidth, ElementName=uc}"/> 
     <TextBox 
      Text="{Binding Path=TextBoxValue, Mode=TwoWay, ElementName=uc}" 
      Width="{Binding Path=TextBoxWidth, ElementName=uc}"/> 
    </StackPanel> 
</UserControl> 
+0

この上の最後の一日を過ごした後、私はあなたの提案を含め、私の作業溶液を、掲載しました。あなたは正しい道で私を送ってきましたが、私のバインディングにTemplatedParent RelativeSourceがなかったので、私は自分のControlTemplate(今編集した投稿)に問題がありました。どうもありがとう! – madsiur

関連する問題