我試圖規劃一個基於mvvm的基礎架構,我決定視圖將通過虛擬機直接綁定到實體。 (vm將持有實體引用,綁定將是o entity.propertyName ...)一些mvvm問題 - 知道哪個視圖正在編輯一個實體
現在我得到了一個問題,當用戶開始在一個視圖中編輯字段時,我想鎖定(使只讀)所有其他視圖綁定到正在編輯的實體。
所以我的問題是: 在我的設計中需要做些什麼改變才能知道誰(哪個視圖)首先開始編輯,何時他完成了......以及如何知道發生了變化從UI(對於不鎖定任何東西)
我試圖規劃一個基於mvvm的基礎架構,我決定視圖將通過虛擬機直接綁定到實體。 (vm將持有實體引用,綁定將是o entity.propertyName ...)一些mvvm問題 - 知道哪個視圖正在編輯一個實體
現在我得到了一個問題,當用戶開始在一個視圖中編輯字段時,我想鎖定(使只讀)所有其他視圖綁定到正在編輯的實體。
所以我的問題是: 在我的設計中需要做些什麼改變才能知道誰(哪個視圖)首先開始編輯,何時他完成了......以及如何知道發生了變化從UI(對於不鎖定任何東西)
首先,您需要定義正是它意味着用戶是「編輯」的實體。
對用戶的部件發出什麼動作,他們開始編輯實體?顯然,當某人在綁定到模型字段的文本框中輸入某些內容時,他們正在編輯該實體。但是,如果有人點擊視圖中的按鈕來清除模型中的屬性值或將其設置爲預定義值,該怎麼辦?這是否被認爲是「編輯」實體?如果他們更改視圖的設置以使其顯示更少的選項,並且由於舊值不再列出,ComboBox會將模型中的值切換爲新值,那該怎麼辦?
對用戶零件發出什麼樣的信號,表示他們正在編輯一個實體?當焦點離開他們的控制時他們完成了嗎?當焦點離開視圖?當他們點擊「確定」或「保存」?
根據這些問題的答案,可以看到幾個簡單的解決方案。我會解釋一個簡單的答案。如果不適用,請澄清上述問題的答案。
假設:
然後下面的工作:
這真的取決於你的程序結構。我有一些類似的要求,我在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獲得了最好的幫助。
選項可能是使用EventAggegator
或使用中介模式來警告其他視圖模型正在編輯特定實體實例。那些視圖模型可以設置一個屬性IsReadonly = true
,它可以在xaml中綁定,以使控件只讀。
只是rasie出編輯事件告訴那些viewmodels,它不再處於reaonly模式。
如果您直接綁定到實體,它應該實現INotifyPropertyChanged
,您的視圖模型可以偵聽它以檢測第一次編輯的發生。
HTH
1.如果一個實體沒有從任何視圖中改變,該怎麼辦? 2.我如何知道編輯何時結束,我可以釋放鎖定? 3.我將如何知道(或正在使用我的基礎設施的其他程序員)在視圖模型中所持有的每個實體的屬性更改事件上註冊視圖模型? – 2010-07-07 20:42:03
1.如果它實現了INotifyPropertyChanged,那麼事件機制仍應如我所描述的那樣工作。 2.我會想象會有一些用戶採取的行動來定義這一點,例如保存,應用或取消按鈕。只需對處理程序進行編碼以便引發事件 3.這被定義爲視圖的行爲,因此在視圖模型中進行相應編碼。您可以創建一個基類,使所有視圖模型從附屬模型中繼承,提出並傾聽這些更改,因此您只需從該類繼承 – aqwert 2010-07-07 20:51:39
這是您的最佳實踐建議? – 2010-07-07 20:36:38
如果實體正在從代碼更改而沒有用戶編輯任何內容,該怎麼辦? – 2010-07-07 20:37:09
你的第一個2的假設是好的3我不知道... – 2010-07-07 20:38:00