2010-06-29 16 views
1

我試圖規劃一個基於mvvm的基礎架構,我決定視圖將通過虛擬機直接綁定到實體。 (vm將持有實體引用,綁定將是o entity.propertyName ...)一些mvvm問題 - 知道哪個視圖正在編輯一個實體

現在我得到了一個問題,當用戶開始在一個視圖中編輯字段時,我想鎖定(使只讀)所有其他視圖綁定到正在編輯的實體。

所以我的問題是: 在我的設計中需要做些什麼改變才能知道誰(哪個視圖)首先開始編輯,何時他完成了......以及如何知道發生了變化從UI(對於不鎖定任何東西)

回答

1

首先,您需要定義正是它意味着用戶是「編輯」的實體。

  1. 對用戶的部件發出什麼動作,他們開始編輯實體?顯然,當某人在綁定到模型字段的文本框中輸入某些內容時,他們正在編輯該實體。但是,如果有人點擊視圖中的按鈕來清除模型中的屬性值或將其設置爲預定義值,該怎麼辦?這是否被認爲是「編輯」實體?如果他們更改視圖的設置以使其顯示更少的選項,並且由於舊值不再列出,ComboBox會將模型中的值切換爲新值,那該怎麼辦?

  2. 對用戶零件發出什麼樣的信號,表示他們正在編輯一個實體?當焦點離開他們的控制時他們完成了嗎?當焦點離開視圖?當他們點擊「確定」或「保存」?

根據這些問題的答案,可以看到幾個簡單的解決方案。我會解釋一個簡單的答案。如果不適用,請澄清上述問題的答案。

假設:

  1. 到模型對象所做除了從數據庫中的數據刷新的任何變化被認爲是編輯,它是否與一個按鈕,複選框來完成,等等
  2. 包含焦點的視圖被認爲是正在進行更改的人
  3. 當視圖失去焦點或用戶保存數據時,「編輯」結束。

然後下面的工作:

  1. 添加「重裝」財產既可以作爲一個靜態屬性或在你的模型
  2. 在你的數據重新加載代碼,設置該屬性「真」的地方,並在finally塊中將其設置爲「false」
  3. 在您的模型對象中(或在視圖模型之間共享的數據結構中以及使用弱字典從模型映射的數據結構中),添加一個包含視圖視圖模型的屬性目前正在編輯實體
  4. 在您的視圖中,在連接視圖模型時向模型對象添加PropertyChanged處理程序
  5. 在處理程序中,如果:a。重新加載標誌是假的,b。目前沒有視圖正在編輯實體,並且c。此視圖的IsKeyboardFocusWithin爲true,然後記錄此視圖當前正在編輯實體的事實
  6. 在每個視圖模型中,將處理程序附加到步驟3中提到的「CurrentlyEditorView」屬性(直接或通過單獨的數據結構)。只要這個propety改變了,如果它是非null而不是當前的視圖模型,設置一個繼承的「鎖定」屬性,導致視圖鎖定。
  7. 在視圖中,添加一個LostFocus事件處理程序,用於檢查模型的當前視圖是否是這一個,如果是,則清除它。
  8. 另外爲保存命令添加一個處理程序來執行相同的操作。
+0

這是您的最佳實踐建議? – 2010-07-07 20:36:38

+0

如果實體正在從代碼更改而沒有用戶編輯任何內容,該怎麼辦? – 2010-07-07 20:37:09

+0

你的第一個2的假設是好的3我不知道... – 2010-07-07 20:38:00

0

這真的取決於你的程序結構。我有一些類似的要求,我在primaryshell鑑於這樣做......

<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獲得了最好的幫助。

0

選項可能是使用EventAggegator或使用中介模式來警告其他視圖模型正在編輯特定實體實例。那些視圖模型可以設置一個屬性IsReadonly = true,它可以在xaml中綁定,以使控件只讀。

只是rasie出編輯事件告訴那些viewmodels,它不再處於reaonly模式。

如果您直接綁定到實體,它應該實現INotifyPropertyChanged,您的視圖模型可以偵聽它以檢測第一次編輯的發生。

HTH

+0

1.如果一個實體沒有從任何視圖中改變,該怎麼辦? 2.我如何知道編輯何時結束,我可以釋放鎖定? 3.我將如何知道(或正在使用我的基礎設施的其他程序員)在視圖模型中所持有的每個實體的屬性更改事件上註冊視圖模型? – 2010-07-07 20:42:03

+0

1.如果它實現了INotifyPropertyChanged,那麼事件機制仍應如我所描述的那樣工作。 2.我會想象會有一些用戶採取的行動來定義這一點,例如保存,應用或取消按鈕。只需對處理程序進行編碼以便引發事件 3.這被定義爲視圖的行爲,因此在視圖模型中進行相應編碼。您可以創建一個基類,使所有視圖模型從附屬模型中繼承,提出並傾聽這些更改,因此您只需從該類繼承 – aqwert 2010-07-07 20:51:39

相關問題