如何在xaml中绑定用户控件?

时间:2012-02-06 13:06:41

标签: c# wpf xaml data-binding user-controls

我有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和一个Button,为了简单起见,我没有添加任何代码。

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

加上我有一个枚举OverviewType,包含None,Project,Person值。

正确更改了属性更改事件,但未刷新用户控件。谁能让我高兴,我解决方案的缺陷在哪里?

我有另一个问题,如何从usercontrols到mainwindow viewmodel进行通信?外汇:数据网格应根据其过滤器进行更改。

非常感谢任何帮助。干杯!

2 个答案:

答案 0 :(得分:4)

尝试在更改属性的支持字段后触发PropertyChanged

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

类似于OverviewType

答案 1 :(得分:4)

这里有不同的问题。

  • 正如Clemens所说,您必须在更新值后触发事件。但这不是主要问题。

  • 第二个问题:您正在影响新的usercontrol 给私人会员,因此您完全绕过了您的财产。

替换

_userControl = new ProjectFilter();

通过

this.UserControl = new ProjectFilter();
  • 第三个问题,与您的问题没有直接关系,但实际上是您的最大问题:您有架构设计问题。您在自己的视图模型中显示UserControl,即anti-pattern。您的viewmodel 必须不知道有关视图的任何内容,因此它必须对视图中的控件有任何引用。您可以从视图模型中激活事件,并在视图中添加事件处理程序,而不是您编写的绑定,以便更新用户控件您的视图