2009-06-16 16 views
6

GroupBoxにUserControlsを表示するアプリケーションがあります。コントロールを表示するには、表示するViewModelを返すメインフォームのViewModelのプロパティにバインドします。フォームが自動的に各ViewModelを表示するために使用するUserControl/Viewを知るようにDataTemplatesを設定しました。WPF Viewは、閉じる時にViewModelプロパティをnullに設定します。

別のUserControlを表示すると、以前のコントロールのViewModelはアクティブになりますが、ビューはWPFによって自動的に破棄されます。

ビューがシャットダウンすると、ViewModelのプロパティへの双方向バインディングがすぐにnullに設定されるため、ViewModelを再度表示すると、すべての値が設定されます。 UIではnullになります。

これは、Viewの終了時に、ビューの終了時に、そのビューに含まれているコントロールの値が破棄されて消去され、バインディングが配置されているためにViewModelにも伝播するためです。

<ComboBox Name="SupervisorDropDown" ItemsSource="{Binding Path=Supervisors}" DisplayMemberPath="sgSupervisor" 
      SelectedValuePath="idSupervisor" SelectedValue="{Binding Path=SelectedSupervisorID}" /> 

:コードは、ユーザーを表示するために使用される私のリソースで

DataTemplates

<DataTemplate DataType="{x:Type vm:HomeViewModel}"> 
    <vw:HomeView /> 
</DataTemplate> 
<DataTemplate DataType="{x:Type vm:SettingsViewModel}"> 
    <vw:SettingsView /> 
</DataTemplate> 
<DataTemplate DataType="{x:Type vm:JobListViewModel}"> 
    <vw:JobListView /> 
</DataTemplate> 

は、私はビューの一つに結合してい制御の

<GroupBox> 
    <ContentControl Content="{Binding Path=RightPanel}" /> 
</GroupBox> 

例を制御します関連するViewModelプロパティ:

public ObservableCollection<SupervisorsEntity> Supervisors 
    { 
     get 
     { 
      return supervisors; 
     } 
    } 

public int? SelectedSupervisorID 
{ 
    get 
    { 
     return selectedSupervisorID; 
    } 
    set 
    { 
     selectedSupervisorID = value; 
     this.OnPropertyChanged("SelectedSupervisorID"); 
    } 
} 

私のViewModelsの値をnullにする方法はありますか?私はそれが閉じる前に、ビューのDataContextをnullに設定する必要があるかもしれないと思っていますが、物事が現在バインドされている方法についてはどうすればいいのか分かりません。

答えて

0

私は1つの解決策を見つけましたが、本当に好きではありません。

DataContext ISがすでにnullに設定されていることが判明しましたが、それは役に立ちません。プロパティがnullに設定される前に発生します。何が起こっているように見えるのは、UserControl/Viewがそれ自体を処理する前にデータバインディングが削除されていないため、コントロールが削除されるときにnull値が伝播するということです。

新しいコンテキストがnullの場合ときのDataContextが変更、次のようにそれでは、私は、コンボボックスに関連するバインディングを削除します。

private void UserControl_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e) 
{ 
    if (e.NewValue == null) 
    { 
     SupervisorDropDown.ClearValue(ComboBox.SelectedValueProperty); 
    } 
} 

をそれが意味するので、私は、この方法の大ファンではありません私が使用するデータバインドされたコントロールごとにそれを行うことを忘れないでください。方法があれば、私はすべてのUserControlを閉じるだけで自動的にバインディングを削除することができますが、それは問題ありませんが、それを行う方法は考えられません。

もう1つの選択肢は、ViewModelsが実行されるまでビューが破壊されないように、アプリケーションを再構成することです。これは問題を完全に回避します。私は別の ユーザーコントロールを表示するとき

+0

この同じ問題が発生しました。視覚的な子のDataContextをnullに設定すると、それが部分的に解決されました。ビューを隠すのではなく、ビューを隠すことで違いはありませんでした。私はまだ完全な解決策を探しています。 – HappyNomad

0

、私は のViewModelにアクティブ前のコントロールを維持するが、 ビューは WPFによって自動的に破棄されます。

私がいる問題は、ビューがシャットダウンすると、任意の二つの方法が のViewModelのプロパティに バインディングがすぐに私はViewModelに 表示したときに再びヌル、 に設定されており すべてのUIの値は に設定されます。

私はWPFでもMVVMでも専門家はいませんが、これについては正しいとは言えません。ビューのWPF処理が問題を引き起こしているとは信じられません。少なくとも私の限られた経験の中で、私はそれが起こるようなことは一度もなかった。私は、犯人がビュー・モデルのコードか、データ・コンテキストのためにどのビュー・モデルが使用されているかをスワップするコードのいずれかであると考えます。

0

さまざまな方法でヌル設定を停止しようとした後、私はあきらめて、代わりに次のように動作させました。ビューを閉じる前にViewModelを読み取り専用にしました。私はIsReadOnlyブール値プロパティを追加した私のViewModelBaseクラスでこれを達成します。次に、ViewModelBase.SetProperty()(下記参照)では、IsReadOnlyがtrueのときにプロパティの変更を無視します。

protected bool SetProperty<T>(ref T backingField, T value, string propertyName) 
    { 
     var change = !IsReadOnly && !EqualityComparer<T>.Default.Equals(backingField, value); 

     if (change) { 
      backingField = value; 
      OnPropertyChanged(propertyName); 
     } 
     return change; 
    } 

私はまだもっと良い解決策を知りたいと思っていますが、このように動作しているようです。

0

私は同じ問題を抱えていました。私のために働いたのは私のSelectedValueBindingsからUpdateSourceTrigger = PropertyChangedを取り除くことでした。

<!--Users DataGrid--> 
<DataGrid Grid.Row="0" ItemsSource="{Binding DealsUsersViewSource.View}" 
    AutoGenerateColumns="False" CanUserAddRows="True" CanUserDeleteRows="False" 
    HorizontalAlignment="Stretch" VerticalAlignment="Stretch"> 
    <DataGrid.Resources> 
     <SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}" Color="#FFC5D6FB"/> 
    </DataGrid.Resources> 
    <DataGrid.Columns> 

      <!--Username Column--> 
      <DataGridComboBoxColumn 
      SelectedValueBinding="{Binding Username}" Header="Username" Width="*"> 
       <DataGridComboBoxColumn.ElementStyle> 
        <Style TargetType="{x:Type ComboBox}"> 
         <Setter Property="ItemsSource" Value="{Binding DataContext.DealsUsersCollection.ViewModels, 
          RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" /> 
         <Setter Property="SelectedValuePath" Value="Username"/> 
         <Setter Property="DisplayMemberPath" Value="Username"/> 
        </Style> 
       </DataGridComboBoxColumn.ElementStyle> 
       <DataGridComboBoxColumn.EditingElementStyle> 
        <Style TargetType="{x:Type ComboBox}"> 
         <Setter Property="ItemsSource" Value="{Binding DataContext.BpcsUsers, 
          RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" /> 
         <Setter Property="SelectedValuePath" Value="Description"/> 
         <Setter Property="DisplayMemberPath" Value="Description"/> 
         <Setter Property="IsEditable" Value="True"/> 
        </Style> 
       </DataGridComboBoxColumn.EditingElementStyle> 
      </DataGridComboBoxColumn> 

      <!--Supervisor Column--> 
      <DataGridComboBoxColumn 
      SelectedValueBinding="{Binding Supervisor}" Header="Supervisor" Width="*"> 
       <DataGridComboBoxColumn.ElementStyle> 
        <Style TargetType="{x:Type ComboBox}"> 
         <Setter Property="ItemsSource" Value="{Binding DataContext.DealsUsersCollection.ViewModels, 
          RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" /> 
         <Setter Property="SelectedValuePath" Value="Username"/> 
         <Setter Property="DisplayMemberPath" Value="Username"/> 
        </Style> 
       </DataGridComboBoxColumn.ElementStyle> 
       <DataGridComboBoxColumn.EditingElementStyle> 
        <Style TargetType="{x:Type ComboBox}"> 
         <Setter Property="ItemsSource" Value="{Binding DataContext.BpcsUsers, 
          RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" /> 
         <Setter Property="SelectedValuePath" Value="Description"/> 
         <Setter Property="DisplayMemberPath" Value="Description"/> 
         <Setter Property="IsEditable" Value="True"/> 
        </Style> 
       </DataGridComboBoxColumn.EditingElementStyle> 
      </DataGridComboBoxColumn> 

      <!--Plan Moderator Column--> 
      <DataGridCheckBoxColumn Binding="{Binding IsPlanModerator}" Header="Plan Moderator?" Width="*"/> 

      <!--Planner Column--> 
      <DataGridCheckBoxColumn Binding="{Binding IsPlanner}" Header="Planner?" Width="*"/> 

    </DataGrid.Columns> 
</DataGrid> 

コンテナビュー:

<!--Pre-defined custom styles--> 
<a:BaseView.Resources> 

    <DataTemplate DataType="{x:Type vm:WelcomeTabViewModel}"> 
     <uc:WelcomeTabView/> 
    </DataTemplate> 
    <DataTemplate DataType="{x:Type vm:UserSecurityViewModel}"> 
     <uc:UserSecurityView/> 
    </DataTemplate> 
    <DataTemplate DataType="{x:Type vm:PackItemRegisterViewModel}"> 
     <uc:PackItemsRegisterView/> 
    </DataTemplate> 

</a:BaseView.Resources> 

<Grid> 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="30"/> 
     <ColumnDefinition Width="*"/> 
     <ColumnDefinition Width="30"/> 
    </Grid.ColumnDefinitions> 

    <Grid.RowDefinitions> 
     <RowDefinition Height="30"/> 
     <RowDefinition Height="*"/> 
     <RowDefinition Height="30"/> 
    </Grid.RowDefinitions> 

    <TabPanel Grid.Column="1" Grid.Row="1"> 
     <TabControl TabStripPlacement="Top" ItemsSource="{Binding TabCollection}" SelectedIndex="{Binding SelectedTabIndex}" 
        DisplayMemberPath="DisplayName" MinWidth="640" MinHeight="480"/> 
    </TabPanel> 

</Grid> 

コンテナのViewModel:

TabCollection.Add(new WelcomeTabViewModel()); 
TabCollection.Add(new UserSecurityViewModel(_userService, _bpcsUsersLookup)); 
TabCollection.Add(new PackItemRegisterViewModel(_packItemService, _itemClassLookup)); 
SelectedTabIndex = 0; 
のPropertyChanged UpdateSourceTriggersは、あなたがそのパターンを使用するときにビューを閉じるのバウンドプロパティに発射するように見えます
0

それはviewmodelの中にあなたのデータには影響しません、ビューが閉じている場合

のLostFocusUpdateSourceTrigger明示を設定し、nullにそのデータを設定します。

<ComboBox Name="SupervisorDropDown" ItemsSource="{Binding Path=Supervisors}" DisplayMemberPath="sgSupervisor" 
SelectedValuePath="idSupervisor" 
SelectedValue="{Binding Path=SelectedSupervisorID, UpdateSourceTrigger=LostFocus}" /> 
関連する問題