3 Stimmen

Aktualisieren der Datentabelle in der Ansicht von viewmodel

Ich habe eine Datentabelle auf eine Ansicht, die an ein Viewmodel gebunden ist. Wenn ich die Ansicht initialisiere, wird die Datentabelle mit Daten aus dem Viewmodel (ObservableCollection) aufgefüllt, wie es sollte. Wenn ich jedoch versuche, eine Suche nach den Daten durchzuführen, wird die Datentabelle nicht aus dem Viewmodel aktualisiert. Wenn ich Breakpoint den Code in meinem Viewmodel, kann ich sehen, die Ergebnisse in der ObservableCollection hat pro meine Suche geändert, aber irgendwie, dass nicht zurück zu der Ansicht kommuniziert wird. Hier ist meine Ansicht und viewmodel (BTW, ich bin mit VS2010 RTM):

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>

4voto

VariableLost Punkte 83

Das war meine Lösung:

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

Der Schlüssel ist die Einstellung von IsAsync=True, die es ermöglicht, den Bildschirm zu malen

2voto

Mlorism Punkte 61

Ich habe 2 Möglichkeiten gefunden, DataGrid zu aktualisieren:

  1. Eine wurde von VariableLost gepostet, sie funktioniert mit INotifyPropertyChanged, hat aber einen Nachteil. Das gesamte DataGrid wird mit Blink-Effekt aktualisiert (verschwindet für einen Sekundenbruchteil). Sieht nicht natürlich aus.
  2. Eine andere Lösung ist die Aktualisierung von ObservableCollection im ViewModel oder Code Behind (wenn Sie nicht MVVM verwenden):

CollectionViewSource.GetDefaultView(collectionName).Refresh();

Sieht natürlicher aus, da nur die von der Auflage betroffenen Zellen verändert werden.

1voto

steveareeno Punkte 1855

Meine Frage wurde in einem Beitrag auf einer anderen Website beantwortet. Anstatt eine neue Instanz der ListOfEmployees in meinem Ansichtsmodell zu erstellen, habe ich einfach die vorhandene gelöscht und die Ergebnisse aus meinem Repository hinzugefügt:

        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);
        }
    }

Das hat gewirkt.

1voto

Stipo Punkte 4486

Ihr vorheriger Code hätte auch funktionieren sollen, aber die "magischen Strings" waren im Weg. Der Name der Eigenschaft ist ListOfEmployees und in ihrem Setter lösen Sie das Ereignis PropertyChanged mit dem Eigenschaftsnamen ListOfEmployee aus. Das 's' fehlt.

Hüten Sie sich vor Ihrem neuen Code. Es wird CollectionChanged Ereignis auf ListOfEmployees für jede Einfügung auslösen, und das könnte Ihre App langsamer machen, wenn Sie viele Einfügungen tun. Für viele Einfügungen wäre es besser, von ObservableCollection abzuleiten und die Methode Reset zu implementieren, die die zugrunde liegenden Elemente löscht, neue Elemente hinzufügt und das Ereignis CollectionChanged vom Typ Reset auslöst.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X