Вид Базовой Модели


Мне нужно написать код в WPF для клиента. Приложение сделано с призмой (не мое решение, они уже были люди, работающие на нем), так что я получил сверкающий чистый новый модуль для работы. Так как это был мой первый раз пишу WPF-код в производство, я хотел обработать код в хорошей форме. Я решил пойти в MVVM.

Я структурированный модуль следующим образом (мне нужно, чтобы переместить RelayCommand и ViewModelBase):

  • Услуг (IItemTypeService.КС, ItemTypeService.ЗС)
  • Просмотр Моделей (ItemTypeViewModel.КС, ItemTypeViewModel.КС, RelayCommand.КС, ViewModelBase.ЗС)
  • Вид (ItemTypeAdminView.в XAML, ItemTypeDetailView.язык XAML)

В ViewModelBase реализует INotifyPropertyChanged в.

В ItemTypeAdminView является основным видом. ItemTypeDetailView пользователь-контроль и помещается в ItemTypeAdminView. В ItemTypeAdminView будет в будущем быть дополнен другими разделами, и эти разделы будут использовать такую же информацию, как ItemTypeDetailView.

Поэтому я сделал модель представления для ItemTypeAdminView, не ItemTypeDetailView. Каждый Пункттип исходит от Linq2SQL (да, я знаю об эф - я не участвовал в этой части), и заворачивают в ItemTypeViewModel поэтому он может реализовать INotifyPropertyChanged в.

Код для ItemTypeAdminViewModel:

public class ItemTypeAdminViewModel : ViewModelBase
{
    #region private fields
    private ICollectionView collectionView;
    private IItemTypeService itemTypeService;
    #endregion

    #region automatic properties
    public ObservableCollection<ItemTypeViewModel> ItemTypes { get; private set; }
    public IEnumerable<Company> Companies { get; private set; }
    public IEnumerable<CompanyGTIN> CompanyGTINs { get; private set; }

    private Company selectedCompany;
    public Company SelectedCompany
    {
        get { return selectedCompany; }
        set
        {
            selectedCompany = value;
            LoadCompanyGTINs();
        }
    }
    #endregion properties

    #region constructors
    public ItemTypeAdminViewModel(IItemTypeService itemTypeService)
    {
        this.itemTypeService = itemTypeService;
        Initialize();
    }
    #endregion

    #region private methods
    private void Initialize()
    {
        //Should I wrap in Try/Catch? Try/Catch is expensive, must find something else...
        ItemTypes = new ObservableCollection<ItemTypeViewModel>(itemTypeService.GetItemTypes());
        Companies = itemTypeService.GetCompanies();
        collectionView = CollectionViewSource.GetDefaultView(ItemTypes);
    }

    private void LoadCompanyGTINs()
    {
        CompanyGTINs = itemTypeService.GetCompanyGTINs(selectedCompany.ID);
        OnPropertyChanged("CompanyGTINs");
    }
    #endregion

    #region commands
    public ICommand GoToFirstItemType
    {
        get
        {
            return new RelayCommand(() => collectionView.MoveCurrentToFirst(),
                () => collectionView.CurrentPosition >= 1);
        }
    }

    public ICommand GoToLastItemType
    {
        get
        {
            return new RelayCommand(() => collectionView.MoveCurrentToLast(),
                () => collectionView.CurrentPosition < (ItemTypes.Count - 1));
        }
    }

    public ICommand NextItemType
    {
        get
        {
            LoadCompanyGTINs();
            return new RelayCommand(() => collectionView.MoveCurrentToNext(),
                () => collectionView.CurrentPosition < (ItemTypes.Count - 1));
        }
    }

    public ICommand PreviousItemType
    {
        get
        {
            return new RelayCommand(() => collectionView.MoveCurrentToPrevious(),
                () => collectionView.CurrentPosition >= 1);
        }
    }
    #endregion
}

И код для ItemTypeDetailView в XAML:

<Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <Grid DataContext="{Binding ItemTypes}">
            <Grid.ColumnDefinitions>
                <ColumnDefinition />
                <ColumnDefinition />
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
            </Grid.RowDefinitions>

            <TextBlock Text="Name:" />
            <TextBox Grid.Column="2" Text="{Binding Name}" />

            <TextBlock Grid.Row="1" Text="Description:" />
            <TextBox Grid.Column="1" Grid.Row="1" Text="{Binding Description}" />

            <TextBlock Grid.Row="2" Text="Manufacturer:" />
            <ComboBox Grid.Column="1" Grid.Row="2"
                      DisplayMemberPath="Name"
                      ItemsSource="{Binding Path=DataContext.Companies, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl, AncestorLevel=2}}"
                      Name="ManufacturerComboBox"
                      SelectedItem="{Binding Mode=TwoWay, Path=DataContext.SelectedCompany, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl, AncestorLevel=2}}"
                      SelectedValue="{Binding ManufacturerID}"
                      SelectedValuePath="ID" />

            <TextBlock Grid.Row="10" Text="Manufacturer Product Code:"/>
            <TextBox Grid.Column="1" Grid.Row="10" Text="{Binding ManufacturerProductCode}" />

            <TextBlock Grid.Row="11" Text="Manufacturer Product GS1 Code:"/>
            <TextBox Grid.Column="1" Grid.Row="11" Text="{Binding ManufacturerProductGS1Code}" />

            <TextBlock Grid.Row="12" Text="GS1GTINID:"/>
            <ComboBox DisplayMemberPath="GTIN"
                      Grid.Column="1" Grid.Row="12"
                      IsSynchronizedWithCurrentItem="True"
                      ItemsSource="{Binding Path=DataContext.CompanyGTINs, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl, AncestorLevel=2}}"
                      SelectedValue="{Binding GS1GTINID}"
                      SelectedValuePath="ID" />
        </Grid>

        <Grid Grid.Row="2">
            <StackPanel Grid.Row="4" Orientation="Horizontal">
                <Button Command="{Binding GoToFirstItemType}">&lt;&lt;</Button>
                <TextBlock Margin="5,0,5,0" />
                <Button Command="{Binding PreviousItemType}">&lt;</Button>
                <TextBlock Margin="5,0,5,0" />
                <Button Command="{Binding NextItemType}">&gt;</Button>
                <TextBlock Margin="5,0,5,0" />
                <Button Command="{Binding GoToLastItemType}">&gt;&gt;</Button>
                <TextBlock Margin="5,0,5,0" />
                <Button Command="{Binding New}">New</Button>
            </StackPanel>
        </Grid>
    </Grid>

Мне очень любопытно, что можно улучшить структуру/код мудрым и/или какие должны быть опущены.



1294
6
задан 19 апреля 2011 в 03:04 Источник Поделиться
Комментарии
1 ответ

Модель представления в целом выглядит хорошо, хотя я бы все-таки предложить некоторые изменения:


  1. Я не вижу, зачем вам нужен collectionView поле. Вы двигаетесь это Текущийэлемент , но ни он, ни весь вид подвергается в любом месте.

  2. общественный метод ICommand NextItemType. Почему вы LoadCompanyGTINs() звонить сюда? У вас есть несколько похожих двигаться... методы, но только вот у вас этот звонок.


По Поводу Зрения:


  1. У вас странная планировка во внутренней сетке. Он имеет две колонки, но вы устанавливаете внутреннюю сетку.Контроль добавленные свойства 1 и 2 , вместо 0 и 1

  2. Как правило, привязки на ваш взгляд выглядят очень странно. В первую очередь я бы порекомендовал никогда не привязать DataContext в Внутренний вид (). Если что-то внутри посмотреть есть отдельный класс DataContext , то это должен быть отдельный вид+с ViewModel. Из-за этой привязки вы должны использовать RelativeSource внутри некоторые другие элементы управления, что не есть хорошо. Привязки внутри первой таблицы, которые не имеют RelativeSource также выглядят странно. Например . С такой привязки, я думаю, он пытается найти имя собственность на ItemTypes коллекции, но это коллекция ObservableCollection , который не имеет такого свойства, так что он не должен работать. То же самое про описание.

  3. Если вам действительно нужно RelativeSource то, по крайней мере попробовать, чтобы избежать использования его с RelativeSource={RelativeSource поиска, AncestorType=элемент управления UserControl, AncestorLevel=2}. Я пытался угадать, каким будет результат источник для привязки, но не повезло. Я бы рекомендовал использовать что-то вроде RelativeSource={RelativeSource поиска, AncestorType=местные:ItemTypeDetailView} вместо этого.

Вообще я бы настаивала только на избавление от этих странных переплетах, на ваш взгляд, остальное более или менее в порядке.

4
ответ дан 19 апреля 2011 в 05:04 Источник Поделиться