2013-09-24 80 views
1

我有一個WPF數據網格綁定到一個EF6 Dbcontext。我有許多功能,例如手動編輯等。WPF EF6 Datagrid單元不會更新編程方式更改,除非用戶編輯單元格

問題 編輯綁定到網格的EF對象不會在網格上更新。但如果我手動編輯一個單元格後,這些背景編輯之一,它立即顯示正確的值。

SCENARIO/SETUP

ViewSources涉及

<Window.Resources> 
<CollectionViewSource x:Key="equipmentViewSource" d:DesignSource="{d:DesignInstance {x:Type HAI_Job_EF_Model:Equipment}, CreateList=True}"/> 
<CollectionViewSource x:Key="equipmentAssociatedDevicesViewSource" 
           Source="{Binding AssociatedDevices, Source={StaticResource equipmentViewSource}}"/>  
</Window.Resources> 

注意,相關聯的設備是一個設備對象內部一個ObservableCollection。

WPF Datagrid的(僅作爲示例份)

<DataGrid x:Name="associatedDevicesDataGrid" Grid.Row="1" AutoGenerateColumns="False" 
           MaxWidth="1200" EnableRowVirtualization="True" 
           RowDetailsVisibilityMode="VisibleWhenSelected" CanUserDeleteRows="False" 
           DataContext="{StaticResource equipmentAssociatedDevicesViewSource}" ItemsSource="{Binding}" 
           CellEditEnding="associatedDevicesDataGrid_CellEditEnding" 
           SelectionChanged="associatedDevicesDataGrid_SelectionChanged" 
           PreviewKeyDown="associatedDevicesDataGrid_PreviewKeyDown" 
           LostFocus="associatedDevicesDataGrid_LostFocus"> 
       <DataGrid.Resources> 
        <!-- DATGRID STYLE CELL: Gives padding space inside cells --> 
        <Style TargetType="DataGridCell"> 
         <Setter Property="Padding" Value="5,5"/> 
         <Setter Property="Template"> 
          <Setter.Value> 
           <ControlTemplate TargetType="{x:Type DataGridCell}"> 
            <Border Padding="{TemplateBinding Padding}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True"> 
             <ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/> 
            </Border> 
           </ControlTemplate> 
          </Setter.Value> 
         </Setter> 
        </Style> 
       </DataGrid.Resources> 
       <DataGrid.Columns> 
        <DataGridTextColumn x:Name="quantityColumn" Header="Qty" MaxWidth="50" 
             Binding="{Binding Quantity, StringFormat={}\{0:N0\}, Mode=TwoWay, UpdateSourceTrigger=LostFocus}"/> 
        <DataGridComboBoxColumn x:Name="typeColumn" Header="Type" MaxWidth="150" 
              ItemsSource="{Binding Source={StaticResource assDevTypeFilteredViewSource}}" 
              SelectedItemBinding="{Binding Path=Type, UpdateSourceTrigger=PropertyChanged}" 
              TextBinding="{Binding Path=Type, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"> 
         <DataGridComboBoxColumn.EditingElementStyle> 
          <Style TargetType="ComboBox"> 
           <Setter Property="IsEditable" Value="True"/> 
           <Setter Property="Text" Value="{Binding Path=Type}"/> 
           <Setter Property="IsSynchronizedWithCurrentItem" Value="True" /> 
           <Setter Property="IsTextSearchEnabled" Value="True" /> 
           <Setter Property="IsTextSearchCaseSensitive" Value="False" /> 
          </Style> 
         </DataGridComboBoxColumn.EditingElementStyle> 
        </DataGridComboBoxColumn> 

        <DataGridTemplateColumn x:Name="certificateNumberColumn" Header="Certificate Number" Width="Auto" MaxWidth="200"> 
         <DataGridTemplateColumn.CellTemplate> 
          <DataTemplate> 
           <ComboBox Name="cbxAssDevCertComboBox" 
              IsEditable="True" IsTextSearchEnabled="True" IsTextSearchCaseSensitive="False" 
              ItemsSource="{Binding GenericFilterResults}" 
              Text="{Binding Path=CertificateNumber, UpdateSourceTrigger=PropertyChanged}" 
              SelectionChanged="cbxAssDevCertComboBox_SelectionChanged"/> 
          </DataTemplate> 
         </DataGridTemplateColumn.CellTemplate> 
        </DataGridTemplateColumn> 
        <DataGridTextColumn x:Name="manufacturerColumn" Header="Manufacturer" Width="Auto" MaxWidth="150" 
             Binding="{Binding Manufacturer, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/> 

背景變化 組合框 「cbxAssDevCertComboBox」 SelectionChanged事件然後更新該其他細胞源對象中的所有值。這是不刷新的更新。

主要選擇受審/考慮的

  1. 我不完全了MVVM,我不跟隨它。我現在太深刻了,無法改變這個項目。我只需要f'n的東西來更新......!

  2. 我無法在Observable集合中包裝每一個EF對象......沒有其他東西需要它,那麼爲什麼這樣呢?那不是CollectionViewSource本質上在做什麼?!

  3. 更新Datagrids ItemSource bindingexpression沒有幫助。

  4. 使用更新

如何更新細胞就像它當我嘗試手動編輯效果的PROGRAMITC編輯後?

我現在已經失去了幾天試圖解決這個問題;任何幫助將不勝感激。

+0

我想你需要在模型上實現'INotifyPropertyChanged',並在值被改變時調用它。 ObservableCollection'會在集合被修改(添加新項目/刪除項目)時通知用戶界面,但當項目的屬性發生變化時,通知用戶界面 - 因爲您需要'INotifyPropertyChanged'。 – Shaamaan

+0

很高興知道可觀察收集和我通知的區別。我認爲使用集合viewsource也一樣嗎?顯然不是我想的。手動觸發綁定刷新怎麼辦? – Asvaldr

+0

你打算如何觸發這種綁定更新? – Shaamaan

回答

2

解決爲他人信息

我找到了答案。我想知道爲什麼我的其他一些網格更新,而這個網格沒有更新。

如果您創建視圖源,如我在OP中顯示的那樣;調用ViewSource.View.Refresh將刷新網格。 我原本沒有這個,因爲刷新時會導致一個ComboboxSelectionChanged事件;然後在無限循環中創建。你也不能僅僅添加一個切換來防止事件的第二次刷新,因爲這個事件可以在安裝過程中多次設置。

解決方案 我用一個bool作爲鎖來防止處理選擇改變的事件中的邏輯。每次處理事件邏輯時都會設置此鎖。鎖只能通過組合框拖放打開事件移除;這確保刷新只發生在用戶做出選擇改變時的預期。

+0

我嘗試'ViewSource.View.Refresh',在我的'CellEditEnding'事件中,但得到一個錯誤消息:''刷新'不允許在一個AddNew或EditItem事務。'我如何終止事務' Refresh'? –

2

ObservableCollection很棒,但它只在添加或刪除項目時才通知UI。它在項目被修改時(即,項目屬性被更改時)不會通知UI。

你需要在你的模型上實現INotifyPropertyChanged接口並且啓動它。

下面是實現該接口的樣本模型類:

public class ModelClass : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 

    protected virtual void OnPropertyChanged(string property) 
    { 
     if (PropertyChanged != null) 
      PropertyChanged(this, new PropertyChangedEventArgs(property)); 
    } 

    protected virtual void OnPropertyChanged<T>(Expression<Func<T>> selectorExpression) 
    { 
     if (selectorExpression == null) 
      throw new ArgumentNullException("selectorExpression"); 
     MemberExpression body = selectorExpression.Body as MemberExpression; 
     if (body == null) 
      throw new ArgumentException("The body must be a member expression"); 
     OnPropertyChanged(body.Member.Name); 
    } 

    string _myValue; 
    public string MyValue 
    { 
     get 
     { 
      return _myValue; 
     } 
     set 
     { 
      _myValue = value; 
      OnPropertyChanged(() => MyValue); 
     } 
    } 
} 

的俏皮拉姆達訣竅是從this SO question採取...

當然你也可以手動從您的代碼的其他部分調用OnPropertyChanged(調整訪問者根據需要或編寫額外的公共方法)。調用OnPropertyChanged應該強制UI爲所顯示的屬性調用getter。

相關問題