Как связать usercontrols в xaml? - PullRequest
       14

Как связать usercontrols в xaml?

0 голосов
/ 06 февраля 2012

У меня есть MainWindow, содержащее сетку данных и «панель фильтров».Панель фильтров может быть изменена с помощью пользовательского ввода (нажатие кнопки).Я пытаюсь добиться этого с привязкой данных.Проблема, с которой я сталкиваюсь, заключается в том, что панель фильтра (которая является пользовательским элементом управления) не загружена или не обновлена.

Mainwindow xaml:

 <Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="250*" />
        <ColumnDefinition Width="253*" />
    </Grid.ColumnDefinitions>
    <DataGrid AutoGenerateColumns="True" Height="200" HorizontalAlignment="Left" Margin="23,28,0,0" Name="dataGrid1" VerticalAlignment="Top" Width="200" ItemsSource="{Binding OverviewableItems}" /> 
    <UserControl Grid.Column="1" Content="{Binding UserControl}" DataContext="{Binding}" Grid.ColumnSpan="2" />

    <Button Content="PersonFilter" Height="23" HorizontalAlignment="Left" Margin="23,268,0,0" Name="buttonPersonFilter" VerticalAlignment="Top" Width="75" Click="buttonPersonFilter_Click" />
    <Button Content="ProjectFilter" Height="23" HorizontalAlignment="Left" Margin="132,268,0,0" Name="buttonProjectFilter" VerticalAlignment="Top" Width="75" Click="buttonProjectFilter_Click" />

</Grid>

код позади:

 private ViewModel _viewModel;
    public MainWindow()
    {
        _viewModel = new ViewModel(new DataProvider());
        DataContext = _viewModel;
        _viewModel.PropertyChanged += _viewModel.SetFilterType;
        InitializeComponent();
    }


    private void buttonProjectFilter_Click(object sender, RoutedEventArgs e)
    {
        _viewModel.OverviewType = OverviewType.Project;
    }

    private void buttonPersonFilter_Click(object sender, RoutedEventArgs e)
    {
        _viewModel.OverviewType = OverviewType.Person;
    }

Первый пользовательский элемент управления:

<Grid>
    <DatePicker Grid.Column="1" Grid.Row="1" Height="25" HorizontalAlignment="Left" Margin="19,18,0,0" Name="datePickerFundingTo" VerticalAlignment="Top" Width="115" Text="{Binding ElementName=ProjectFilter, Path=FundingTo}" />
</Grid>

код для этого пользовательского элемента управления только такой:

 public DateTime FundingTo { get; set; }
 public ProjectFilter()
    {
        FundingTo = DateTime.Now;

        InitializeComponent();
    }

Другой пользовательский элемент управления: просто содержит TextBox и кнопку, радидля простоты я не добавил никакого кода к нему.

ViewModel главного окна:

public class ViewModel  : INotifyPropertyChanged
{
    private UserControl _userControl;

    public UserControl UserControl
    {
        get { return _userControl; }
        set
        {
            if (_userControl == value)
            {
                return;
            }
            OnPropertyChanged("UserControl");
            _userControl = value;
        }
    }

    private OverviewType _overviewType = OverviewType.None;
    public OverviewType OverviewType
    {
        get { return _overviewType; }
        set
        {
            if (_overviewType == value)
            {
                return;
            }
            OnPropertyChanged("OverviewType");
            _overviewType = value;
        }
    }

    private ObservableCollection<IOverviewItem> _overviewableItems;
    public ObservableCollection<IOverviewItem> OverviewableItems
    {
        get { return _overviewableItems; }
        set
        {
            if (_overviewableItems == value)
            {
                return;
            }
            _overviewableItems = value;
        }
    }

    private readonly DataProvider _dataProvider;

    public event PropertyChangedEventHandler  PropertyChanged;

    public ViewModel(DataProvider dataProvider)
    {
        _dataProvider = dataProvider;
    }

    public void SetFilterType(object sender, EventArgs eventArgs)
    {

        switch (_overviewType)
        {
            case OverviewType.Project:
                _userControl = new ProjectFilter();
                break;
            case OverviewType.Person:
                _userControl = new PersonFilter();
                break;
        }
    }

    public void OnPropertyChanged(string name)
    {
        if (PropertyChanged == null)
            return;

        var eventArgs = new PropertyChangedEventArgs(name);
        PropertyChanged(this, eventArgs);
    }  
}

плюс у меня есть enum OverviewType со значениями None, Project, Person.

Событие изменения свойства сработало правильно, но пользовательский элемент управления не обновляется.Может ли кто-нибудь осветить меня, где недостаток в моем решении?

И другой вопрос, который у меня есть, как я могу общаться от пользовательских элементов управления до модели представления главного окна?Форекс: сетку данных следует менять в соответствии с фильтром.

Любая помощь будет принята с благодарностью.Ура!

Ответы [ 2 ]

4 голосов
/ 06 февраля 2012

Здесь разные проблемы.

  • Как сказал Клеменс, вы должны запустить свое событие после того, как значение будет обновлено. Но это не главная проблема здесь.

  • Вторая проблема: вы затрагиваете своего нового usercontrol для частного участника , поэтому вы полностью обходите свою собственность.

Заменить

_userControl = new ProjectFilter();

от

this.UserControl = new ProjectFilter();
  • Третья проблема, которая напрямую не связана с вашим вопросом, но на самом деле является вашей самой большой проблемой : у вас проблема проектирования архитектуры . Вы выставляете в своей модели представления UserControl, который является анти-узором . Ваша модель представления не должна ничего знать о представлении, поэтому НЕ ДОЛЖНА иметь какие-либо ссылки на элементы управления внутри представления. Вместо привязки, которую вы написали, вы можете запустить событие из модели представления и добавить обработчик событий в ваше представление, чтобы ваше представление обновляло usercontrol.
4 голосов
/ 06 февраля 2012

Попробуйте запустить PropertyChanged после изменения поля поддержки свойства:

public UserControl UserControl
{
     get { return _userControl; }
     set
     {
         if (_userControl != value) 
         {
            _userControl = value;              // first
             OnPropertyChanged("UserControl"); // second
         }
     } 
}

Аналогично для OverviewType.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...