2012-01-31 60 views
0

我实现使用实体作为我的模型的MVVM模式...当我实例化我添加了二传手的模型来实现在视图模型的propertyChange通知一个的PropertyChanged处理对象捕捉领域的变化实体对象之内...MVVM WCF实体模型......如何使用实体时,为你的模型

当我通过代码步我发现后,我被多次烧制的属性更改事件的对象之内修改字段... 它使我相信我做错了什么...

我想使用实体作为我的模型,因为我不想重新创建对象作为障碍物...

任何可以在下列的代码库的任何故障会导致在DataGrid字段被修改的SelectedCompany.PropertyChanged火,曾多次...

我期待的是,该属性更改事件只会火一次,我有点困惑,为什么它触发多次...

是不是错在二传手添加propertyChange事件......

这里是视图模型...

public class CompanyMaintenanceVM : INotifyPropertyChanged 
{ 
private ServiceHandler _serviceHandler = new ServiceHandler(); 
private bool _ignorePropertyChange = false; //by default we will execute on every property change... 

public CompanyMaintenanceVM() 
{ 
    _companyList = new ObservableCollection<Company>(_serviceHandler.GetCompanies().ToList()); 
    _selectedCompany = _companyList.First(); 
    UpdateCommand = new RelayCommand(Update) { IsEnabled = true }; 
    SearchCommand = new RelayCommand(Search) { IsEnabled = true }; 

    _companyTypeList = new ObservableCollection<CompanyType>(_serviceHandler.GetCompanyTypes().ToList()); 
} 

private string _selectedKey; 
public string SelectedKey 
{ 
    get { return _selectedKey; } 
    set 
    { 
     if (_selectedKey != value) 
     { 
      _selectedKey = value; 
      OnPropertyChanged("SelectedKey"); 
     } 
    } 
} 


private Company _selectedCompany = new Company(); 
public Company SelectedCompany 
{ 
    get { return _selectedCompany; } 
    set 
    { 
     if (_selectedCompany != value) 
     { 
      _selectedCompany = value; 
      OnPropertyChanged("SelectedCompany"); 
      SelectedCompany.PropertyChanged += new PropertyChangedEventHandler(SelectedCompany_PropertyChanged); 
     } 
    } 
} 

private ObservableCollection<Company> _companyList; 
public ObservableCollection<Company> CompanyList 
{ 
    get { return _companyList; } 
    set 
    { 
     _companyList = value; 
     OnPropertyChanged("CompanyList"); 
    } 

} 

private ObservableCollection<CompanyType> _companyTypeList; 
public ObservableCollection<CompanyType> CompanyTypeList 
{ 
    get { return _companyTypeList; } 
    set { _companyTypeList = value; } 
} 

#region INotifyPropertyChanged Members 
public event PropertyChangedEventHandler PropertyChanged; 
private void OnPropertyChanged(string propertyName) 
{ 
    if (PropertyChanged != null) 
     PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
    switch (propertyName) 
    { 
     case "SelectedKey": 
      if (_ignorePropertyChange == false) 
      { 
       SelectedKeyChanged(); 
      } 
      _ignorePropertyChange = false; 
      break; 
     case "SelectedCompany": 
      _ignorePropertyChange = true; 
      SelectedKey = SelectedCompany.CompanyID; 

      break; 
    } 
} 

void SelectedCompany_PropertyChanged(object sender, PropertyChangedEventArgs e) 
{ 
    // 
} 
#endregion 

private void SelectedKeyChanged() 
{ 
    var companies = _serviceHandler.GetCompanyByID(SelectedKey); 
    if (companies.FirstOrDefault() != null) 
    { 
     CompanyList = new ObservableCollection<Company>(companies); 
     SelectedCompany = CompanyList.First(); 
    } 
    else 
    { 
     MessageBox.Show("No Company Record Exsists Matching CompanyID " + _selectedKey); 
    } 
} 

private ICommand _updateCommand; 
public ICommand UpdateCommand 
{ 
    get 
    { 
     if (_updateCommand == null) 
      _updateCommand = new Updater(); 
     return _updateCommand; 
    } 
    set 
    { 
     _updateCommand = value; 
    } 
} 

private class Updater : ICommand 
{ 
    #region ICommand Members 

    public bool CanExecute(object parameter) 
    { 
     return true; 
    } 
    public event EventHandler CanExecuteChanged; 
    public void Execute(Object parameter) 
    { 

    } 
    #endregion 
} 

private void Update() 
{ 
    _serviceHandler.UpdateRepository(SelectedCompany); 
    _serviceHandler.CommitRepository(); 

} 


private ICommand _searchCommand; 
public ICommand SearchCommand 
{ 
    get 
    { 
     if (_searchCommand == null) 
      _searchCommand = new Searcher(); 
     return _searchCommand; 
    } 
    set 
    { 
     _searchCommand = value; 
    } 
} 
private class Searcher : ICommand 
{ 
    #region ICommand Members 

    public bool CanExecute(object parameter) 
    { 
     return true; 
    } 
    public event EventHandler CanExecuteChanged; 
    public void Execute(Object parameter) 
    { 

    } 
    #endregion 
} 

private void Search() 
{ 



} 


} 

这里是XAML ...

<Window x:Class="XERP.Client.WPF.CompanyMaintenance.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="Company Maintenance" Height="800" Width="600"> 

    <Grid> 
     <Grid.Resources> 

     </Grid.Resources> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="25"></RowDefinition> 
      <RowDefinition Height="422*"></RowDefinition> 
     </Grid.RowDefinitions> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="156*"></ColumnDefinition> 
      <ColumnDefinition Width="422*"></ColumnDefinition> 
     </Grid.ColumnDefinitions> 
     <TextBlock HorizontalAlignment="Center" Grid.Column="1" Text="Company Maintenance Form" 
        FontSize="13" 
        Margin="130,3,129,5"></TextBlock> 
     <Menu IsMainMenu="True" Grid.ColumnSpan="2" Margin="2,2,370,2" Width="180"> 
      <MenuItem Header="_File" > 
       <MenuItem Header="_New" Command="New"> 
       </MenuItem> 
       <MenuItem Header="_Save" 
          IsCheckable="True" 
          Command="{Binding UpdateCommand}" Click="SaveMenuItem_Click"> 
       </MenuItem> 
       <MenuItem Header="_Exit" Command="Close"> 
       </MenuItem> 
      </MenuItem> 
      <MenuItem Header="_Edit"> 
       <MenuItem Header="_Cut" Command="Cut"> 
       </MenuItem> 
       <MenuItem Header="_Copy" Command="Copy"> 
       </MenuItem> 
       <MenuItem Header="_Paste" Command="Paste"> 
       </MenuItem> 
      </MenuItem> 
      <MenuItem Header="_Tools" /> 
      <MenuItem Header="_Actions" /> 
      <MenuItem Header="_Help" /> 
     </Menu> 

     <GridSplitter Grid.Row="1" Grid.Column="0" HorizontalAlignment="Right" Width="4" Background="Yellow"/> 

     <ListView Grid.Row="1" Grid.Column="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="5" 
       ItemsSource="{Binding CompanyList}" 
        SelectedItem="{Binding SelectedCompany, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" 
        SelectionMode="Single" 
        IsSynchronizedWithCurrentItem="True" 
        > 
      <ListView.ItemTemplate> 
       <DataTemplate > 
        <TextBlock Text="{Binding Path=CompanyID, Mode=TwoWay}" Margin="5"/> 
       </DataTemplate> 
      </ListView.ItemTemplate> 
     </ListView> 
     <TabControl Grid.Row="1" Grid.Column="1" HorizontalAlignment="Stretch" 
        VerticalAlignment="Stretch"> 
      <TabItem Header="Detail"> 
       <Grid> 
        <Grid.RowDefinitions> 
         <RowDefinition Height="46"></RowDefinition> 
         <RowDefinition Height="657*"></RowDefinition> 
        </Grid.RowDefinitions> 
        <Grid.ColumnDefinitions> 
         <ColumnDefinition Width="165*"></ColumnDefinition> 
         <ColumnDefinition Width="246*"></ColumnDefinition> 
        </Grid.ColumnDefinitions> 
        <StackPanel HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Orientation="Horizontal" Grid.Row="0" Grid.ColumnSpan="2"> 
         <Button Width="100" Height="20" Margin="10" 
           Command="{Binding SearchCommand}">Company...</Button> 
         <TextBox Width="100" Height="20" Margin=" 10" 
           Text="{Binding Path=SelectedKey, Mode=TwoWay}" 
           /> 
        </StackPanel> 
        <StackPanel HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Orientation="Vertical" Grid.Row="1" Grid.Column="0"> 
         <TextBlock HorizontalAlignment="Right" VerticalAlignment="Top" Margin="8">Name:</TextBlock> 
         <TextBlock HorizontalAlignment="Right" VerticalAlignment="Top" Margin="8">Description:</TextBlock> 
         <TextBlock HorizontalAlignment="Right" VerticalAlignment="Top" Margin="8">Type:</TextBlock> 
        </StackPanel> 
        <StackPanel HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Orientation="Vertical" Grid.Row="1" Grid.Column="1"> 
         <TextBox HorizontalAlignment="Left" VerticalAlignment="Top" Margin="5" Width="200" 
           Text="{Binding Path=SelectedCompany.Name, Mode=TwoWay}" 
           /> 
         <TextBox 
          HorizontalAlignment="Left" VerticalAlignment="Top" Margin="5" Width="200" 
           Text="{Binding Path=SelectedCompany.Description, Mode=TwoWay}" 
           /> 
         <ComboBox HorizontalAlignment="Left" Width="200" Margin="5" 
           ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.CompanyTypeList, Mode=TwoWay}" 
           DisplayMemberPath="Type" 
           SelectedValuePath="CompanyTypeID" 
           SelectedValue="{Binding Path=SelectedCompany.CompanyTypeID, Mode=TwoWay}"/> 
         <TextBox Height="23" Name="ghost" Width="0" /> 
        </StackPanel> 
       </Grid> 


      </TabItem> 
      <TabItem Header="List" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"> 
       <Grid> 
        <DataGrid AutoGenerateColumns="False" 
         ItemsSource="{Binding CompanyList}" 
         SelectedItem="{Binding SelectedCompany, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" 
         SelectionMode="Single" 
         IsSynchronizedWithCurrentItem="True" 

         > 
         <DataGrid.Columns> 
          <DataGridTextColumn Binding="{Binding CompanyID, Mode=TwoWay}" 
               Header="ID" Width="auto" IsReadOnly="True"/> 
          <DataGridTextColumn Binding="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=LostFocus}" 
               Header="Name" Width="Auto"/> 
          <DataGridTextColumn Binding="{Binding Description, Mode=TwoWay, UpdateSourceTrigger=LostFocus}" 
               Header="Description" Width="Auto"/> 
          <DataGridComboBoxColumn Header="Type" Width="Auto" 
           SelectedValueBinding ="{Binding CompanyTypeID, Mode=TwoWay, UpdateSourceTrigger=LostFocus}" 
           DisplayMemberPath="Type" 
           SelectedValuePath="CompanyTypeID"> 
           <DataGridComboBoxColumn.ElementStyle> 
            <Style TargetType="ComboBox"> 
             <Setter Property="ItemsSource" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.CompanyTypeList, Mode=TwoWay}"/> 
            </Style> 
           </DataGridComboBoxColumn.ElementStyle> 
           <DataGridComboBoxColumn.EditingElementStyle> 
            <Style TargetType="ComboBox"> 
             <Setter Property="ItemsSource" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.CompanyTypeList, Mode=TwoWay}"/> 
            </Style> 
           </DataGridComboBoxColumn.EditingElementStyle> 
          </DataGridComboBoxColumn> 
         </DataGrid.Columns> 
        </DataGrid> 
        <TextBox Height="23" Name="ghost2" Width="0" /> 
       </Grid> 
      </TabItem> 
     </TabControl> 
    </Grid> 
</Window> 
+0

有趣的我删除了双向的ListView的结合,现在的属性更改为selectedcompany仅发生两次...... – 2012-01-31 20:44:20

+0

感觉就像每一个双向绑定你就会跳闸的ViewModels属性更改事件。我在正确的轨道上吗? – 2012-01-31 20:45:17

+0

我觉得这是非常重要的,了解绑定...的性质,因为ListView控件只是当前记录的选择,没有编辑可以做它不应该被束缚双向...你应该只绑定双向编辑时会能够在该文本框和数据网格需要双向绑定,因为他们将允许从视图属性的编辑和将需要被通知当一个改变让对方可以用变化 – 2012-01-31 20:49:30

回答

0

注意使用具有双向约束力和IsSynchronizedWithCurrentItem =“真”则selectedItem的 - 也许有你得到你的往返。

和你的事业以下?

if (_selectedCompany != value) 
    { 
     _selectedCompany = value; 
     OnPropertyChanged("SelectedCompany"); 
     SelectedCompany.PropertyChanged += new PropertyChangedEventHandler(SelectedCompany_PropertyChanged); //<-- whats that? 
    } 

为什么你这样做?

private void OnPropertyChanged(string propertyName) 
{ 
if (PropertyChanged != null) 
    PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 


switch (propertyName)//why you do this? 
{ 
    case "SelectedKey": 
     if (_ignorePropertyChange == false) 
     { 
      SelectedKeyChanged(); 
     } 
     _ignorePropertyChange = false; 
     break; 
    case "SelectedCompany": 
     _ignorePropertyChange = true; 
     SelectedKey = SelectedCompany.CompanyID; 

     break; 
} 
} 
+0

好点apropriately更新IsSynchronizedWithCurrentItem = True ...我已经删除了,因为这更适合于CollectionViewSource ... SelectedCompany.PropertyChange事件声明是为我分配属性更改处理的集合,你会建议什么? – 2012-02-06 15:22:51

+0

我选择使用SelectedKey的单独属性,而不是直接绑定到等效的Selected Property ... – 2012-02-06 15:26:44

+0

至于允许绑定的文本框被修改,然后当它被修改时,它会触发搜索特定的记录它被修改为... – 2012-02-06 15:51:15