WPF查看设置视图模型属性设置为null收盘上(WPF View sets ViewModel pr

2019-07-28 20:05发布

我在那里我在分组框中显示用户控件的应用程序。 以显示控件,我结合在主模的视图模型,它返回到被显示的视图模型的特性。 我有设置,使表单自动知道用户控件/视图用来显示每个视图模型其中的DataTemplates。

当我显示不同的用户控件,我保持先前的控制的视图模型活性,但视图是通过WPF自动丢弃。

说我遇到的问题是,当视图关闭,任何双向绑定到视图模型属性被立即设置为空,所以当我显示视图模型再次所有值都只是设置为空的UI。

我想这是因为作为景观的一部分逼抢其配置和它所包含的控件清除任何值,因为绑定到位,他们传播到视图模型为好。

在我的资源的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>

我在观看一个正在结合控制的实例:

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

以及相关的视图模型属性:

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

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

如何停止我的观点,我的ViewModels归零值的任何想法? 我想,也许我需要视图设置为空的DataContext的它倒闭前,但我不知道如何去与目前事情结合的方式。

Answer 1:

我发现一个可能的解决方案,但我真的不喜欢它。

原来,在DataContext被设置为空已,但这并不能帮助。 它发生前的属性设置为null。 这似乎是发生的是,用户控件/视图部署的本身之前,所以当控制被删除空值向下传播的数据绑定不被删除。

所以当DataContext的变化,如果新的上下文为null,则我删除的组合框的相关绑定,如下所示:

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

我不是这种方法的大风扇,因为这意味着我必须记得这样做对每一个数据绑定控件我使用。 如果有一种方法,我可以只是每个用户控件只是删除其绑定后会自动关闭,这将是好的,但我想不出任何办法做到这一点。

另一种选择可能是只调整自己的应用程序,这样的观点并不被摧毁,直到做的ViewModels - 这将完全回避这个问题。



Answer 2:

当我显示不同的用户控件,我保持先前的控制的视图模型活性,但视图是通过WPF自动丢弃。

说我遇到的问题是,当视图关闭,任何双向绑定到视图模型属性被立即设置为空,所以当我显示视图模型再次所有值都只是设置为空的UI。

我在任WPF或MVVM专家,但一些关于这个不健全的权利。 我有麻烦相信WPF处置的看法是造成你的问题。 最起码,在我有限的经验,我从来没有过这样的事情发生。 我怀疑罪魁祸首是在视图模型或视图模型被用于的datacontext代码swaping出或者代码。



Answer 3:

试图阻止通过各种方式零设定后,我放弃了,而不是得到它的工作如下。 我所做的视图模型只读关闭其观点之前。 我在ViewModelBase类,在这里我添加了一个IsReadOnly布尔属性做到这一点。 然后在ViewModelBase.SetProperty()(见下文),我忽略任何属性发生变化时IsReadOnly是真实的。

    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;
    }

这似乎是这样工作,但我还是很想知道一个更好的解决方案。



Answer 4:

我有同样的问题。 什么工作对我来说是从我SelectedValueBindings去除UpdateSourceTrigger =的PropertyChanged。 的PropertyChanged UpdateSourceTriggers似乎火在关闭的意见绑定属性,当您使用模式:

<!--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>

容器视图模型:

TabCollection.Add(new WelcomeTabViewModel());
TabCollection.Add(new UserSecurityViewModel(_userService, _bpcsUsersLookup));
TabCollection.Add(new PackItemRegisterViewModel(_packItemService, _itemClassLookup));
SelectedTabIndex = 0;


Answer 5:

设置UpdateSourceTrigger明确,以引发LostFocus

如果视图被关闭,并将其数据为空,它在视图模型上的数据没有影响。

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


文章来源: WPF View sets ViewModel properties to null on closing
标签: c# .net wpf mvvm