2

一部の Microsoft アプリケーションの「ウィザード」コンポーネントのように機能するアプリケーションを作成しています。これを表すために、2 つの ViewModel があります。

class WizardVm {
    public string Name { get; set; }
    public ICommand QuitCommand { get { /* ommitted */ } }
    public WizardStepVm CurrentStep { get; set; }
}

class WizardStepVm {
    public string StepName { get; set; }
    public string StepText {get; set; }
}

ビューでWizardVmは、ウィンドウにバインドし、ウィンドウWizardStepVm内のコンテンツ パネルにバインドします。プログラムでコンテンツ コントロールを作成し、次のように WizardView に追加しています。

// in the "DataContextChanged" handler for the WizardView
var bn = new Binding("CurrentStep");
bn.Mode = BindingMode.OneWay;

var contentControl = new ContentControl();
contentControl.SetBinding(ContentControl.ContentProperty, bn);
WizardViewStackPanel.Children.Add(contentControl);

これは、WizardView が最初に作成されたときに正しくレンダリングされます。ただし、CurrentStep変更された場合、ビューはこれを反映するように更新されません。CurrentStep は変更されますが、ContentControl は引き続き元の WizardStepVm を表示します。また、古い WizardStepVm は引き続きメモリ内に存在し、その文字列プロパティは引き続き (ビューから) 変更できます。

どうしてこれなの?バインドされている ViewModel の変更を反映するようにコンテンツ コントロールを変更するには、どうすればよいですか?

(実際には、これをプログラムで行うのには十分な理由があります。ただし、xaml ソリューションも高く評価されています。)

4

2 に答える 2

2

まず、ビューモデルはINotifyPropertyChangedを実装するか、BindingMode OneTimeを使用する必要があります(この投稿を参照)

それにもかかわらず、ビューモデルの最初のアプローチとデータテンプレートを使用すると、非常に簡単にやりたいことができます

public class WizardVm {
   public string Name { get; set; }
   public ICommand QuitCommand { get { /* ommitted */ } }
   public object CurrentStep { get; set; }//raise OnPropertyChanged("CurrentStep"); in your setter!!
}

public class WizardStep1Vm {
   public string StepName { get; set; }
   public string StepText {get; set; }
}

public class WizardStep2Vm {
   public string StepName { get; set; }
   public string StepText {get; set; }
}

window.xaml

<Window>
<Window.Resources>
    <DataTemplate DataType="{x:Type local:WizardStep1Vm}">
        <!--your view for step1 goes here-->
        <local:MyStep1View/>
    </DataTemplate>
    <DataTemplate DataType="{x:Type local:WizardStep2Vm}">
        <!--your view for step2 goes here-->
        <local:MyStep2View/>
    </DataTemplate>
</Window.Resources>
  <Grid>
    <Grid.RowDefinitions>
        <RowDefinition />
        <RowDefinition />
    </Grid.RowDefinitions>

    <TextBlock Grid.Row="0" Text="{Binding Name}" />

    <ContentPresenter Content="{Binding CurrentStep}"/>

  </Grid>
</Window>

ビューモデルでCurrentStepプロパティを設定するときはいつでも。コンテンツコントロールに正しいビューが表示されます。そうでない場合は、DataTemplateがありません;)

于 2012-07-03T11:21:23.827 に答える
2

クラスはINotifyPropertyChangedインターフェイスを実装して、プロパティの 1 つが変更されるたびに UI に通知する必要があります。

class WizardStepVm : INotifyPropertyChanged {
    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(String info)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }
    private string m_stepName;
    public string StepName {
      get {
        return m_stepName;
      }
      set {
        m_stepName = value; 
        NotifyPropertyChanged("StepName");
      }
    }
    /* etc... */
}
于 2012-07-03T11:07:32.853 に答える