[WPF, MVVM] Покритикуйте код на досуге
От: skodnik  
Дата: 09.09.10 12:23
Оценка: 4 (1)
Хочу на общее обсуждение выставить следующий код.
Только начал применять MVVM и мне очень не нравится то, что я реально получаю.
Может более опытные товарищи подскажут что можно оптимизировать.

Итак, начнем с постановки задачи:
Реализовать форму с двумя компонентами: ComboBox и DataGrid. Данные в DataGrid зависят от выбранного значения в ComboBox и при смене этого

значения должны обновляться асинхронно.

Решение:
1. Сначала создадим форму на XAML:


  <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="25"></RowDefinition>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>
        <ComboBox 
            Grid.Row="0"
            Height="23" 
            HorizontalAlignment="Left"  
            Name="comboBox1" 
            VerticalAlignment="Top" 
            Width="208" 
            SelectedItem="{Binding Path=ItemSelected}"
            ItemsSource="{Binding Path=ComboItems}"
            DisplayMemberPath="Name" />
        <DataGrid 
            Grid.Row="1"
            AutoGenerateColumns="True" 
            ItemsSource="{Binding GridItems, IsAsync=True}" 
            Name="dataGrid1">
        </DataGrid>
    </Grid>


тут мы нарисовали комбобокс с биндингом и грид с биндингом с указанием IsAsync=True. Т.е. при запросе датасорса для грида вся форма подвисать

не будет.

2. Создаем ViewModel — самое интересное



public class ViewModel : ViewModelBase
    {
        public RandomFilesViewModel()
        {
            // Инициализация comboItems
            comboItems = SomeDAO.Get();
            if (comboItems != null)
                if (comboItems.Count > 0)
                    ItemSelected = comboItems[0];
        }

        public List<SomeType> GridItems
        {
            get
            {
                // !!!!!!!! Результат зависит от выбранного значения в комбобоксе
                return SomeFunctionToGetGridItems(MarketSelected);
            }
        }


        public ObservableCollection<ComboItemType> ComboItems
        {
            get
            {
                return сomboItems;
            }
            set
            {
                if (value != сomboItems)
                {
                    сomboItems = value;
                    OnPropertyChanged("ComboItems");
                }
            }
        }
        private ObservableCollection<ComboItemType> comboItems;

        private ComboItemType itemSelected;
        public ComboItemType ItemSelected
        {
            get { return itemSelected; }
            set
            {
                if (itemSelected != value)
                {
                    itemSelected = value;
                    OnPropertyChanged("ItemSelected");
                    // !!!!!!!! Для обновления грида
                    OnPropertyChanged("GridItems");
                }
            }
        }
    }



Ну вот так, теперь в реальной программе ViewModel передаем в качестве DataContext'a и запускаем.
Что мне в этом коде не нравится:
1. Мне не нравится кусок кода:

// !!!!!!!! Для обновления грида
OnPropertyChanged("GridItems");


потому что у меня несколько форм реализованы по такому принципу, только в одном случае от комбобокса зависит грид, в другом случае другой контрол и т.д.
Я бы хотел вынести public ComboItemType ItemSelected в базовый класс и наследоваться, но не получается изза такой завязки.

2. Мне не нравится в конструкторе инициализация значений комбобокса. Хоро было бы эти значения в конструктор передавать, но я решил использовать Unity и категорически не знаю как Unity сказать где брать эти значения.

Буду очень благодарен за критику.
Re: [WPF, MVVM] Покритикуйте код на досуге
От: LF  
Дата: 09.09.10 12:38
Оценка: 6 (2)
S>1. Мне не нравится кусок кода:
S>

S> // !!!!!!!! Для обновления грида
S> OnPropertyChanged("GridItems");

S>потому что у меня несколько форм реализованы по такому принципу, только в одном случае от комбобокса зависит грид, в другом случае другой контрол и т.д.
S>Я бы хотел вынести public ComboItemType ItemSelected в базовый класс и наследоваться, но не получается изза такой завязки.
Можно подписаться на PropertyChanged таким образом:

public RandomFilesViewModel() {
  this.PropertyChanged += OnPropertyChanged
}

private void OnPropertyChanged(object sender, PropertyChangedEventArgs e){
  if (e.PropertyName == "ItemSelected"){
    OnPropertyChanged("GridItems");
  }
}


S>2. Мне не нравится в конструкторе инициализация значений комбобокса. Хоро было бы эти значения в конструктор передавать, но я решил использовать Unity и категорически не знаю как Unity сказать где брать эти значения.


public RandomFilesViewModel(ISomeDAO dao)
        {
            // Инициализация comboItems
            comboItems = dao.Get();
            if (comboItems != null)
                if (comboItems.Count > 0)
                    ItemSelected = comboItems[0];
        }

Где то раньше написать такое:
container.Register<ISomeDAO, SomeDAO>()
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.