一些mvvm问题 - 知道哪个视图当前正在编辑实体

时间:2010-06-29 20:50:09

标签: c# wpf mvvm

我正在尝试计划基于mvvm的基础架构,我决定通过vm将视图直接绑定到实体。 (vm将保存实体引用,绑定将为entity.propertyName ...)

现在我遇到了一个问题,当用户开始在一个视图中编辑字段时,我想锁定(make readonly)绑定到正在编辑的实体的所有其他视图。

所以我的问题是: 在我的设计中我需要做些什么改变才能知道谁(什么视图)首先开始编辑,何时完成...以及如何知道改变不是来自ui(因为没有锁定任何东西)< / p>

3 个答案:

答案 0 :(得分:1)

首先,您必须准确定义用户“编辑”实体的含义。

  1. 用户的哪些操作表明他们开始编辑实体?很明显,当有人在绑定到模型字段的TextBox中键入内容时,他们正在编辑实体。但是,如果有人单击视图中的按钮来清除模型中的属性值或将其设置为预定义值,该怎么办?那被认为是“编辑”实体吗?如果他们更改视图的设置以便显示更少的选项,并且ComboBox将模型中的值切换为新值,因为旧的值不再列出会怎样?

  2. 用户的哪些操作表明他们编辑了一个实体?当焦点离开他们所控制的控件时,它们是否完成?当焦点离开视图时?当他们点击“确定”或“保存”?

  3. 根据这些问题的答案,可以使用几种简单的解决方案。我将解释一个简单的答案。如果不适用,请澄清上述问题的答案。

    假设:

    1. 除了从数据库刷新数据之外,对模型对象所做的任何更改都被视为编辑,无论是通过按钮,复选框等完成,
    2. 包含焦点的视图被视为正在进行更改的视图
    3. 当视图失去焦点或用户保存数据时,“编辑”结束。
    4. 然后以下内容将起作用:

      1. 将“重新加载”属性添加为静态属性或模型中的某个位置
      2. 在您的数据重新加载代码中,将此属性设置为“true”,并在finally块中将其设置为“false”
      3. 在模型对象中(或在视图模型之间共享并使用弱字典从模型映射的数据结构中),添加包含当前正在编辑实体的视图的视图模型的属性
      4. 在视图中,在附加视图模型时向模型对象添加PropertyChanged处理程序
      5. 在处理程序中,如果:a。重新加载标志为false,b。当前没有视图正在编辑实体,而c。此视图的IsKeyboardFocusWithin为true,然后记录此视图当前正在编辑实体的事实
      6. 在每个视图模型中,将处理程序附加到步骤3中提到的“CurrentlyEditorView”属性(直接或通过单独的数据结构)。每当此属性更改时,如果它是非null而不是当前视图模型,请设置继承的“已锁定”属性,从而导致视图锁定。
      7. 在视图中,添加一个LostFocus事件处理程序,用于检查模型的当前视图是否为此视图,如果是,则清除它。
      8. 还为执行相同操作的“保存”命令添加处理程序。

答案 1 :(得分:0)

这实际上取决于你的程序结构。我有一些类似的要求,我在我的原始视图中做到了这一点......

<Grid wpfi:VisualStateAssistant.CurrentVisualState="{Binding Path=CurrentVisualState}">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="640" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="480" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="ActiveFormStateGroup">
                <VisualStateGroup.Transitions>

                </VisualStateGroup.Transitions>
                <VisualState x:Name="Searching">
                    <Storyboard>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
                                                       Storyboard.TargetName="SearchHeaderView">
                            <DiscreteObjectKeyFrame KeyTime="0"
                                                    Value="{x:Static Visibility.Visible}" />
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
                                                       Storyboard.TargetName="SearchNavigationView">
                            <DiscreteObjectKeyFrame KeyTime="0"
                                                    Value="{x:Static Visibility.Visible}" />
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
                                                       Storyboard.TargetName="SearchResultsView">
                            <DiscreteObjectKeyFrame KeyTime="0"
                                                    Value="{x:Static Visibility.Visible}" />
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
                                                       Storyboard.TargetName="DoctorsModuleShell">
                            <DiscreteObjectKeyFrame KeyTime="0"
                                                    Value="{x:Static Visibility.Collapsed}" />
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
                                                       Storyboard.TargetName="DoctorsModuleNavigationView">
                            <DiscreteObjectKeyFrame KeyTime="0"
                                                    Value="{x:Static Visibility.Collapsed}" />
                        </ObjectAnimationUsingKeyFrames>
                    </Storyboard>

                </VisualState>
                <VisualState x:Name="DoctorEdit">
                    <Storyboard>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
                                                       Storyboard.TargetName="SearchHeaderView">
                            <DiscreteObjectKeyFrame KeyTime="0"
                                                    Value="{x:Static Visibility.Collapsed}" />
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
                                                       Storyboard.TargetName="SearchNavigationView">
                            <DiscreteObjectKeyFrame KeyTime="0"
                                                    Value="{x:Static Visibility.Collapsed}" />
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
                                                       Storyboard.TargetName="SearchResultsView">
                            <DiscreteObjectKeyFrame KeyTime="0"
                                                    Value="{x:Static Visibility.Collapsed}" />
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
                                                       Storyboard.TargetName="DoctorsModuleShell">
                            <DiscreteObjectKeyFrame KeyTime="0"
                                                    Value="{x:Static Visibility.Visible}" />
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
                                                       Storyboard.TargetName="DoctorsModuleNavigationView">
                            <DiscreteObjectKeyFrame KeyTime="0"
                                                    Value="{x:Static Visibility.Visible}" />
                        </ObjectAnimationUsingKeyFrames>
                    </Storyboard>

                </VisualState>

            </VisualStateGroup>
            <VisualStateGroup x:Name="VisualAlertsStateGroup">
                <VisualStateGroup.Transitions>

                </VisualStateGroup.Transitions>
                <VisualState x:Name="DialogShowing">
                    <Storyboard>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
                                                       Storyboard.TargetName="rectangle">
                            <DiscreteObjectKeyFrame KeyTime="0"
                                                    Value="{x:Static Visibility.Visible}" />
                        </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>
                <VisualState x:Name="DialogNotShowing">
                    <Storyboard>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
                                                       Storyboard.TargetName="rectangle">
                            <DiscreteObjectKeyFrame KeyTime="0"
                                                    Value="{x:Static Visibility.Collapsed}" />
                        </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>
                <VisualState x:Name="IsWaiting">
                    <Storyboard>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
                                                       Storyboard.TargetName="rectangle">
                            <DiscreteObjectKeyFrame KeyTime="0"
                                                    Value="{x:Static Visibility.Visible}" />
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
                                                       Storyboard.TargetName="WaitControl">
                            <DiscreteObjectKeyFrame KeyTime="0"
                                                    Value="{x:Static Visibility.Visible}" />
                        </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>
                <VisualState x:Name="IsNotWaiting">
                    <Storyboard>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
                                                       Storyboard.TargetName="rectangle">
                            <DiscreteObjectKeyFrame KeyTime="0"
                                                    Value="{x:Static Visibility.Collapsed}" />
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
                                                       Storyboard.TargetName="WaitControl">
                            <DiscreteObjectKeyFrame KeyTime="0"
                                                    Value="{x:Static Visibility.Collapsed}" />
                        </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>

            </VisualStateGroup>
            <VisualStateGroup x:Name="DialogFormsStateGroup">
                <VisualStateGroup.Transitions>

                </VisualStateGroup.Transitions>
                <VisualState x:Name="ShowContactInfoEdit">
                    <Storyboard>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
                                                       Storyboard.TargetName="rectangle">
                            <DiscreteObjectKeyFrame KeyTime="0"
                                                    Value="{x:Static Visibility.Visible}" />
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
                                                       Storyboard.TargetName="ContactInfoDatagridView">
                            <DiscreteObjectKeyFrame KeyTime="0"
                                                    Value="{x:Static Visibility.Visible}" />
                        </ObjectAnimationUsingKeyFrames>
                    </Storyboard>

                </VisualState>
                <VisualState x:Name="HideContactInfoEdit">
                    <Storyboard>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
                                                       Storyboard.TargetName="rectangle">
                            <DiscreteObjectKeyFrame KeyTime="0"
                                                    Value="{x:Static Visibility.Collapsed}" />
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
                                                       Storyboard.TargetName="ContactInfoDatagridView">
                            <DiscreteObjectKeyFrame KeyTime="0"
                                                    Value="{x:Static Visibility.Collapsed}" />

                        </ObjectAnimationUsingKeyFrames>
                    </Storyboard>

                </VisualState>
                <VisualState x:Name="ShowDoctorTaxonomyEdit">
                    <Storyboard>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
                                                       Storyboard.TargetName="rectangle">
                            <DiscreteObjectKeyFrame KeyTime="0"
                                                    Value="{x:Static Visibility.Visible}" />
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
                                                       Storyboard.TargetName="DoctorsTaxonomyEditView">
                            <DiscreteObjectKeyFrame KeyTime="0"
                                                    Value="{x:Static Visibility.Visible}" />

                        </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>
                <VisualState x:Name="HideDoctorTaxonomyEdit">
                    <Storyboard>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
                                                       Storyboard.TargetName="rectangle">
                            <DiscreteObjectKeyFrame KeyTime="0"
                                                    Value="{x:Static Visibility.Collapsed}" />
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
                                                       Storyboard.TargetName="DoctorsTaxonomyEditView">
                            <DiscreteObjectKeyFrame KeyTime="0"
                                                    Value="{x:Static Visibility.Collapsed}" />

                        </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>

            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>

        <DockPanel Grid.Column="0"
                   Grid.Row="0"
                   Grid.ColumnSpan="3"
                   Grid.RowSpan="3">

            <!--TOP-->
            <Grid ShowGridLines="False"
                  DockPanel.Dock="Top">

                <views:SearchHeaderView x:Name="SearchHeaderView" />

            </Grid>
            <!--BOTTOM-->
            <Grid ShowGridLines="false"
                  DockPanel.Dock="Bottom">

                <views:SearchNavigationView x:Name="SearchNavigationView" />
                <views:DoctorsModuleNavigationView  x:Name="DoctorsModuleNavigationView"
                                                    Visibility="Collapsed" />

            </Grid>

            <!--FILL-->
            <Grid ShowGridLines="False">

                <views:SearchResultsView x:Name="SearchResultsView" />
                <views:DoctorsModuleShell x:Name="DoctorsModuleShell"
                                          Visibility="Collapsed" />
            </Grid>

        </DockPanel>
        <Rectangle x:Name="rectangle"
                   RadiusX="2"
                   RadiusY="2"
                   Grid.Column="0"
                   Grid.Row="0"
                   Grid.ColumnSpan="3"
                   Grid.RowSpan="3"
                   Fill="{StaticResource modalFormHitTestRectangleBrush}"
                   IsHitTestVisible="True"
                   Visibility="Collapsed" />

        <controls:WaitingControl x:Name="WaitControl"
                                 Width="100"
                                 Height="100"
                                 Visibility="Collapsed"
                                 Grid.Column="1"
                                 Grid.Row="1" />

        <views:ContactInfoDatagridView x:Name="ContactInfoDatagridView"
                                       Grid.Column="1"
                                       Grid.Row="1"
                                       Visibility="Collapsed" />
        <views:DoctorsTaxonomyEditView x:Name="DoctorsTaxonomyEditView"
                                       Grid.Column="1"
                                       Grid.Row="1"
                                       Visibility="Collapsed" />

    </Grid>

基本上我将visualstatemanager数据绑定到我的主视图模型上的属性,该属性将根据我创建的枚举触发各种视觉状态。我从Karl Shifflets Stuff Application那里得到了最好的帮助。

答案 2 :(得分:0)

一个选项是使用EventAggegator或使用Mediator模式来警告其他视图模型正在编辑特定实体实例。那些视图模型可以设置一个属性IsReadonly = true,它可以绑定在xaml中以使控件只读。

刚刚编辑一个编辑事件,告诉那些视图模型它不再处于reaonly模式。

如果您直接绑定到实体,它应该实现您的视图模型可以监听的INotifyPropertyChanged,以便检测第一次编辑。

HTH