Wpf Reusable Window Model / Template

I am trying to understand and learn a little more about WPF.

In a WPF project with 30 windows, all windows should have:

  • the same toolbar (with buttons: new, edit, delete, view and close)
  • same status bar
  • Each window should have a tabcontrol with 2 TabItem. The contents of the first TabItem may vary depending on the window. The second TabItem should always contain a datagrid with different columns according to the window.

"Logical sequence":

  • Open the window
  • user enters parameters in the first TabItem
  • user presses search button
  • data is displayed in datagarid in second TabItem
  • user clicks on new / edit / delete / view
  • show data editing window

new/edit/view delete gridview. " " !

winform , 30 , . , gridview, , ..

, "", "NewItem", , , "NewItem",

This is the form with the first tab selected

This is the fom with the second tab selected

- WPF?

WPF , ?

,

+4
2

, , , .

, WPF, , "" , winforms, WPF.

WPF, " ", , . - .

, ViewModels, , .

"" ViewModel DataBinding.

, , , /- .

, , , , WPF:

1 -

WPF , , , "" :

public class Bindable : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged(string propertyName)
    {
        var handler = PropertyChanged;
        if (handler != null)
            handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

2 - / ViewModels

, , "" , ViewModel, , "Child":

public class ViewModelBase<T>: Bindable where T: Bindable
{
    private T _child;
    public T Child
    {
        get { return _child; }
        set
        {
            _child = value;
            OnPropertyChanged("Child");
        }
    }
}
  • , :

enter image description here

  • , OnPropertyChanged() .

3 -

Button s. Click Commands, ViewModel, .

DelegateCommand:

//Dead-simple implementation of ICommand
//Serves as an abstraction of Actions performed by the user via interaction with the UI (for instance, Button Click)
public class Command : ICommand
{
    public Action Action { get; set; }

    public void Execute(object parameter)
    {
        if (Action != null)
            Action();
    }

    public bool CanExecute(object parameter)
    {
        return IsEnabled;
    }

    private bool _isEnabled = true;
    public bool IsEnabled
    {
        get { return _isEnabled; }
        set
        {
            _isEnabled = value;
            if (CanExecuteChanged != null)
                CanExecuteChanged(this, EventArgs.Empty);
        }
    }

    public event EventHandler CanExecuteChanged;

    public Command(Action action)
    {
        Action = action;
    }
}

, ViewModel:

public class ViewModelBase<T>: Bindable where T: Bindable
{
    private T _child;
    public T Child...

    public Command SearchCommand { get; private set; }
    public Command NewCommand { get; private set; }
    public Command EditCommand { get; private set; }
    public Command ViewCommand { get; private set; }
    public Command DeleteCommand { get; private set; }
}

Action, , ( Buttons). , , - .

:

public class ViewModelBase<T>: Bindable where T: Bindable
{
     //... all of the above.

    //in the constructor:
    public ViewModelBase()
    {
        SearchCommand = new Command(Search);
        NewCommand = new Command(New);
        //... And so on...
    }

    //Actions for the commands:
    private void Search()
    {
        //... your search logic here.
    }

    private void New()
    {
        //... your New logic here...
    }

    //... And so on...
}

:. , DataGrid, , / .

, Command IsEnabled, , , System.Windows.ICommand.CanExecuteChanged. WPF / . , :

NewCommand.IsEnabled = false; //disables the "New" Button
DeleteCommand.IsEnabled = true; //enables the "Delete" Button

4 - DataGrid

.

DataGrid, ListBox, ListView, ComboBox, ItemsControl WPF , , .

WPF ObservableCollection<T>, , // . WPF .

, DataGrid, , ViewModelBase:

public class ViewModelBase<T, TItems>: Bindable where T: Bindable where TItems: class
{
   //... All of the above...
}

Collection:

public class ViewModelBase<T, TItems>: Bindable where T: Bindable where TItems: class
{
   //... All of the above...

    private ObservableCollection<TItems> _searchResults;
    public ObservableCollection<TItems> SearchResults
    {
        get { return _searchResults; }
        private set
        {
            _searchResults = value;
            OnPropertyChanged("SearchResults");
        }
    }

, , , , Button , , , :

    private TItems _selectedItem;
    public TItems SelectedItem
    {
        get { return _selectedItem; }
        set
        {
            _selectedItem = value;

            NewCommand.IsEnabled = value != null;
            ViewCommand.IsEnabled = value != null;
            DeleteCommand.IsEnabled = value != null;
        }
    }
}

, " ", . New, View Delete Button, DataGrid, , . .

5 - (TabItem 1)

, , "" .

, , winforms, :

  • 1 - .
  • 2 - Items DataGrid , , , , Intellisense ( List<object> ) .
  • 3 - , , . , will work, , DataGrid .

, , 30 Windows

, , - :

enter image description here

, , ViewModel , :

public class PersonViewModel: Bindable
{
    public string LastName { get; set; }

    public string FirstName { get; set; }

    public string City { get; set; }

    public string PostalCode { get;set; }
}

, , . OneWay . , Bindable, Parent ViewModel T.

UserControl:

<UserControl x:Class="WpfApplication1.PersonView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="100"/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>

        <Label HorizontalAlignment="Right" Grid.Row="0" Grid.Column="0" Content="Last Name:" />
        <Label HorizontalAlignment="Right" Grid.Row="1" Grid.Column="0" Content="First Name:" />
        <Label HorizontalAlignment="Right" Grid.Row="2" Grid.Column="0" Content="City:" />
        <Label HorizontalAlignment="Right" Grid.Row="3" Grid.Column="0" Content="Postal Code:" />

        <TextBox Grid.Row="0" Grid.Column="1" Margin="2" Text="{Binding LastName}"/>
        <TextBox Grid.Row="1" Grid.Column="1" Margin="2" Text="{Binding FirstName}"/>
        <TextBox Grid.Row="2" Grid.Column="1" Margin="2" Text="{Binding City}"/>
        <TextBox Grid.Row="3" Grid.Column="1" Margin="2" Text="{Binding PostalCode}"/>
    </Grid>
</UserControl>

, , WPF, - .

6 - DataTemplates

WPF , View , ViewModel, DataTemplate s , App.xaml Application.Resources:

<Application x:Class="WpfApplication1.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:WpfApplication1"
             StartupUri="MainWindow.xaml">

    <Application.Resources>

        <DataTemplate DataType="{x:Type local:PersonViewModel}">
            <local:PersonView/>
        </DataTemplate>
    </Application.Resources>

, , XAML.

, , . , .

+8

, (Search, new, edit..etc..) mainwindow.xaml. , - :

(usercontrols imo), .

<MainWindow>

   <!-- Toolbar -->
   <ContentControl Content="{Binding CurrentTabView}" /> <!-- Where CurrentTabView is of type interface that all your views implement -->

   <!-- Status bar -->

</MainWindow>

ViewModel:

Public IView CurrentTabView { get; set; } //All usercontrol viewmodels implement IView

, : mainwindow, , ?

- MessageSenders/MessageListeners

SendMessage(MessageTokens.SearchToken, new NotificationEventArgs<bool>(null, true)); 

SimpleMvvmToolKit , . , .

+1

All Articles