2010-03-18 6 views
2

J'ai une DataGrid sur une vue qui est liée à un modèle de vue. Lorsque j'initialise la vue, le DataGrid est rempli avec les données du viewmodel (ObservableCollection) comme il se doit. Cependant, avec j'essaie de faire une recherche sur les données, le DataGrid n'est pas actualisé depuis le viewmodel. Quand je repère le code dans mon modèle, je peux voir que les résultats dans ObservableCollection ont changé selon ma recherche, mais d'une manière ou d'une autre, cela n'est pas communiqué à la vue. Voici mon avis et viewmodel (BTW, j'utilise VS2010 RTM):Actualiser DataGrid sur viewmodel

namespace Attendance.ViewModels 
{ 
    public class EmployeeSelectViewModel : ViewModel, INotifyPropertyChanged 
    { 
     #region Entity list and constructor 
    public EmployeeSelectViewModel() 
    { 
     { 
      Initialize(); 
     } 
    } 

    private void Initialize() 
    { 
     if (employeeRpository == null) 
      employeeRpository = new EmployeeRepository(); 

     ListOfEmployees = new ObservableCollection<EmployeeDto>(employeeRpository.GetEmployees(true)); 
    } 

    private EmployeeRepository employeeRpository; 

    private ObservableCollection<EmployeeDto> listOfEmployees; 
    public ObservableCollection<EmployeeDto> ListOfEmployees 
    { 
     get { return listOfEmployees; } 
     set 
     { 
      if (listOfEmployees != value) 
      { 
       listOfEmployees = value; 
       NotifyPropertyChanged("ListOfEmployee"); 
      } 
     } 
    } 

    private EmployeeDto selectedEmployee; 
    public EmployeeDto SelectedEmployee 
    { 
     get { return selectedEmployee; } 
     set 
     { 
      if (selectedEmployee != value) 
      { 
       selectedEmployee = value; 
       NotifyPropertyChanged("SelectedEmployee"); 
      } 
     } 
    } 

    #endregion 

    #region UI control references 

    /// <summary> 
    /// search text property 
    /// </summary> 
    private string searchText; 
    public string SearchText 
    { 
     get { return searchText; } 
     set 
     { 
      if (searchText != value) 
      { 
       searchText = value; 
       NotifyPropertyChanged("SearchText"); 
      } 
     } 
    } 

    public string Location { get; set; } 

    #endregion 

    #region Relay Commands 

    /// <summary> 
    /// new command 
    /// </summary> 
    private ViewCommand newCommand; 
    public ViewCommand NewCommand 
    { 
     get 
     { 
      if (newCommand == null) 
       newCommand = new ViewCommand(param => this.NewEmployee()); 
      return newCommand; 
     } 
    } 
    private void NewEmployee() 
    { 
     NavigationActions.NewEmployeeView(); 
    } 

    /// <summary> 
    /// edit command 
    /// </summary> 
    private ViewCommand editCommand; 
    public ViewCommand EditCommand 
    { 
     get 
     { 
      if (editCommand == null) 
      { 
       editCommand = new ViewCommand(param => this.EditEmployee()); 
      } 
      return editCommand; 
     } 
    } 

    private void EditEmployee() 
    { 
     NavigationActions.OpenEmployeeView(SelectedEmployee); 
    } 

    /// <summary> 
    /// save command 
    /// </summary> 
    private ViewCommand saveCommand; 
    public ViewCommand SaveCommand 
    { 
     get 
     { 
      if (saveCommand == null) 
      { 
       saveCommand = new ViewCommand(
         param => this.SaveEmployee(), 
         param => this.CanSaveEmployee 
         ); 
      } 
      return saveCommand; 
     } 
    } 

    public void SaveEmployee() 
    { 
     employeeRpository.SaveChanges(); 
    } 

    private bool CanSaveEmployee 
    { 
     get { return true; } 
    } 

    /// <summary> 
    /// clear search command 
    /// </summary> 
    private ViewCommand clearSearchCommand; 
    public ViewCommand ClearSearchCommand 
    { 
     get 
     { 
      if (clearSearchCommand == null) 
       clearSearchCommand = new ViewCommand(param => this.ClearSearch()); 
      return clearSearchCommand; 
     } 
    } 

    private void ClearSearch() 
    { 
     this.SearchText = string.Empty; 
     ListOfEmployees = new ObservableCollection<EmployeeDto>(employeeRpository.GetEmployees(true)); 
    } 

    /// <summary> 
    /// search command 
    /// </summary> 
    private ViewCommand searchCommand; 
    public ViewCommand SearchCommand 
    { 
     get 
     { 
      if (searchCommand == null) 
       searchCommand = new ViewCommand(param => this.SearchEmployee()); 
      return searchCommand; 
     } 
    } 

    private void SearchEmployee() 
    { 
     if (this.SearchText == string.Empty || this.SearchText == null) 
     { 
      NavigationActions.ShowError("Search Employees.", "Please enter your search text ..."); 
      return; 
     } 
     ListOfEmployees = new ObservableCollection<EmployeeDto>(employeeRpository.GetEmployeesByQuery(SearchText, Location)); 
    } 

    /// <summary> 
    /// exit command 
    /// </summary> 
    private ViewCommand exitCommand; 
    public ViewCommand ExitCommand 
    { 
     get 
     { 
      if (exitCommand == null) 
      { 
       exitCommand = new ViewCommand(param => this.ExitWindow()); 
      } 
      return exitCommand; 
     } 
    } 

    private void ExitWindow() 
    { 
     NavigationActions.CloseCurrentView(); 
    } 
    #endregion 


    #region INotifyPropertyChanged Members 

    public event PropertyChangedEventHandler PropertyChanged; 

    public void NotifyPropertyChanged(String info) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(info)); 
     } 
    } 

    #endregion 
    } 
} 

<Window x:Class="Attendance.Views.EmployeeSelectView" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:vm="clr-namespace:Attendance.ViewModels" 
    Title="Employee Maintenance" FocusManager.FocusedElement="{Binding ElementName=txtSearchCriteria}" 
    Height="525" Width="800" WindowStartupLocation="CenterScreen" WindowState="Normal" 
    WindowStyle="SingleBorderWindow" Icon="Images/gb_icon.png"> 
<Window.DataContext> 
    <vm:EmployeeSelectViewModel /> 
</Window.DataContext> 
<Window.Resources> 
    <ResourceDictionary> 
     <ResourceDictionary.MergedDictionaries> 
      <ResourceDictionary Source="Themes/DataGrid.Generic.xaml" /> 
     </ResourceDictionary.MergedDictionaries> 
     <!--xml data start--> 
     <XmlDataProvider x:Key="LocationData" XPath="LocationList/LocationItem" Source="XMLData/Location.xml"/> 
     <!--xml data end--> 
    </ResourceDictionary> 
</Window.Resources> 
<Grid Width="775"> 
    <DockPanel HorizontalAlignment="Left" Width="770"> 
     <!-- TOOLBAR --> 
     <DockPanel DockPanel.Dock="Top" MinHeight="30" Margin="5"> 
      <ToolBar FontWeight="Bold"> 
       <!-- NEW --> 
       <Button Name="btnNew" Command="{Binding Path=NewCommand}"> 
        <Button.ToolTip> 
         <StackPanel> 
          <Label FontWeight="Bold" Background="SteelBlue" Foreground="White"> 
           Create a new Customer 
          </Label> 
          <TextBlock Padding="10" TextWrapping="WrapWithOverflow" Width="200"> 
          Create a new customer in a new Window tab. 
          </TextBlock> 
          <Line Stroke="SteelBlue" StrokeThickness="1" X2="200" /> 
          <StackPanel Orientation="Horizontal"> 
           <Image Margin="2" Source="Images/new.png"/> 
           <Label>Press F1 for more help</Label> 
          </StackPanel> 
         </StackPanel> 
        </Button.ToolTip> 
        <StackPanel Orientation="Horizontal"> 
         <Image Source="Images/new.png" Width="22" Height="22" Margin="2"/> 
         <Label VerticalAlignment="Center">_New</Label> 
        </StackPanel> 
       </Button> 
       <!-- EDIT --> 
       <Button Name="btnEdit" Command="{Binding Path=EditCommand}"> 
        <Button.ToolTip> 
         <StackPanel> 
          <Label FontWeight="Bold" Background="SteelBlue" Foreground="White"> 
           Edit the current record 
          </Label> 
          <TextBlock Padding="10" TextWrapping="WrapWithOverflow" Width="200"> 
          Edit the current selected Customer. 
          </TextBlock> 
          <Line Stroke="SteelBlue" StrokeThickness="1" X2="200" /> 
          <StackPanel Orientation="Horizontal"> 
           <Image Margin="2" Source="Images/dialog-information.png"/> 
           <Label>Press F1 for more help</Label> 
          </StackPanel> 
         </StackPanel> 
        </Button.ToolTip> 

        <StackPanel Orientation="Horizontal"> 
         <Image Source="Images/edit.png" Width="22" Height="22" Margin="2" /> 
         <Label VerticalAlignment="Center">_Edit</Label> 
        </StackPanel> 
       </Button> 
       <!-- SEARCH --> 
       <Separator /> 
       <TextBox Name="txtSearchCriteria" 
        MinWidth="300" Margin="5" 
        BorderThickness="1" BorderBrush="LightGray" 
        FontWeight="Normal" Foreground="Gray" Text="{Binding Path=SearchText}"> 
       </TextBox> 
       <Button Name="btnSearch" Command="{Binding Path=SearchCommand}"> 
        <Button.ToolTip> 
         <StackPanel> 
          <Label FontWeight="Bold" Background="SteelBlue" Foreground="White"> 
           Search 
          </Label> 
          <TextBlock Padding="10" TextWrapping="WrapWithOverflow" Width="200"> 
          Search a specific Customer. 
          </TextBlock> 
          <Line Stroke="SteelBlue" StrokeThickness="1" X2="200" /> 
          <StackPanel Orientation="Horizontal"> 
           <Image Margin="2" Source="Images/find.png"/> 
           <Label>Press F1 for more help</Label> 
          </StackPanel> 
         </StackPanel> 
        </Button.ToolTip> 
        <StackPanel Orientation="Horizontal"> 
         <Image Source="Images/find.png" Width="22" Height="22" Margin="2" /> 
         <Label VerticalAlignment="Center">_Find</Label> 
        </StackPanel> 
       </Button> 
       <Button Name="btnClearSearch" Command="{Binding Path=ClearSearchCommand}"> 
        <Button.ToolTip> 
         <StackPanel> 
          <Label FontWeight="Bold" Background="SteelBlue" Foreground="White"> 
           Search 
          </Label> 
          <TextBlock Padding="10" TextWrapping="WrapWithOverflow" Width="200"> 
          Clear search results. 
          </TextBlock> 
          <Line Stroke="SteelBlue" StrokeThickness="1" X2="200" /> 
          <StackPanel Orientation="Horizontal"> 
           <Image Margin="2" Source="Images/find.png"/> 
           <Label>Press F1 for more help</Label> 
          </StackPanel> 
         </StackPanel> 
        </Button.ToolTip> 
        <StackPanel Orientation="Horizontal"> 
         <Label VerticalAlignment="Center">_Clear Search</Label> 
        </StackPanel> 
       </Button> 
       <!-- EXIT --> 
       <Separator /> 
       <Button Name="btnExit" Command="{Binding Path=ExitCommand}"> 
        <Button.ToolTip> 
         <StackPanel> 
          <Label FontWeight="Bold" Background="SteelBlue" Foreground="White"> 
           Start the application 
          </Label> 
          <TextBlock Padding="10" TextWrapping="WrapWithOverflow" Width="200"> 
          Start the main application with the M-V-MV pattern. 
          </TextBlock> 
          <Line Stroke="SteelBlue" StrokeThickness="1" X2="200" /> 
          <StackPanel Orientation="Horizontal"> 
           <Image Margin="2" Source="Images/dialog-information.png"/> 
           <Label>Press F1 for more help</Label> 
          </StackPanel> 
         </StackPanel> 
        </Button.ToolTip> 

        <StackPanel Orientation="Horizontal"> 
         <Image Source="Images/exit.png" Width="22" Height="22" Margin="2" /> 
         <Label VerticalAlignment="Center">_Exit</Label> 
        </StackPanel> 
       </Button> 
      </ToolBar> 
     </DockPanel> 
     <!-- LIST --> 
     <DockPanel DockPanel.Dock="Top" MinHeight="30" Margin="0,0,0,5"> 
      <Label>Location:</Label> 
      <ComboBox Name="cboLocation" Grid.Column="1" Grid.Row="4" 
           ItemsSource="{Binding Source={StaticResource LocationData}}" 
           DisplayMemberPath="location_text" SelectedValuePath="location_value" 
           SelectedValue="{Binding Path=Location}" 
           HorizontalAlignment="Left" Width="175" Margin="4" /> 
     </DockPanel> 
     <DockPanel Margin="5"> 
      <DataGrid ItemsSource="{Binding Path=ListOfEmployees}" AutoGenerateColumns="False" IsReadOnly="True" 
       Name="dgEmployee" SelectionMode="Single" SelectionUnit="FullRow" CanUserResizeColumns="True" 
       SelectedItem="{Binding Path=SelectedEmployee}" GridLinesVisibility="Horizontal"> 
       <DataGrid.Columns> 
        <DataGridTextColumn Header="Employee ID" Width="SizeToCells" MinWidth="125" Binding="{Binding EmployeeID}" /> 
        <DataGridTextColumn Header="First Name" Width="SizeToCells" MinWidth="200" Binding="{Binding FirstName}" /> 
        <DataGridTextColumn Header="Last Name" Width="SizeToCells" MinWidth="200" Binding="{Binding LastName}" /> 
        <DataGridTextColumn Header="Location" Width="SizeToCells" MinWidth="125" Binding="{Binding Location}" /> 
        <DataGridCheckBoxColumn x:Name="Active" Header="Active" Binding="{Binding active}" MinWidth="75" /> 
       </DataGrid.Columns> 
      </DataGrid> 
     </DockPanel> 
    </DockPanel> 
</Grid> 

Répondre

1

Votre ancien code aurait dû fonctionner, mais des «chaînes magiques» vous ont gêné. Le nom de propriété est ListOfEmployees et, dans son setter, vous déclenchez un événement PropertyChanged avec le nom de propriété ListOfEmployee. 's' est manquant.

Méfiez-vous de votre nouveau code. Cela déclenchera l'événement CollectionChanged sur ListOfEmployees pour chaque insertion, ce qui peut ralentir votre application si vous effectuez plusieurs insertions. Pour de nombreuses insertions, il est préférable de dériver de ObservableCollection et d'implémenter la méthode Reset qui efface les éléments sous-jacents, ajoute de nouveaux éléments et soulève l'événement CollectionChanged de type Reset.

1

Ma question a répondu à un poste sur un autre site. Au lieu de créer une nouvelle instance des ListOfEmployees dans mon modèle de vue, je viens raclé le seul et ajouté les résultats existants de mon dépôt:

 private void SearchEmployee() 
    { 
     if (String.IsNullOrEmpty(this.SearchText) || String.IsNullOrEmpty(this.Location)) 
     { 
      NavigationActions.ShowError("Search Employees.", "Please enter your search text and select a location..."); 
      return; 
     } 

     // clear the list and repopulate based on the search criteria 
     if (ListOfEmployees != null) 
     { 
      ListOfEmployees.Clear(); 

      IList<EmployeeDto> iList = employeeRpository.GetEmployeesByQuery(SearchText, Location, IsActive); 
      foreach (EmployeeDto value in iList) 
       ListOfEmployees.Add(value); 
     } 
    } 

qui a fait l'affaire.

1

C'était ma solution:

<DataGrid Name="dgrid" ItemsSource="{Binding UserSettings, IsAsync=True}" AutoGenerateColumns="False"> 

La clé étant le réglage de isAsync = True, permet à la peinture de l'écran pour se produire

Questions connexes