DataTemplate中的WPF ItemsSource绑定

时间:2014-04-15 19:48:54

标签: c# wpf xaml

我已经创建了一个自定义控件,用于在我的应用程序中选择状态,称为StateSelector。如果我将它放在我的UserControl并绑定ItemsSource(通过名为StateList的自定义属性),它工作正常。但是在DataTemplate中使用相同的绑定不起作用。

这是我的StateSelector.xaml

<UserControl x:Class="MyNamespace.StateSelector"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:Local="clr-namespace:MyNamespace"
    Height="21" Width="60">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>
        <ComboBox Grid.Column="0"
              Name="cboState"
              SelectedItem="{Binding Path=CurrentState, Mode=TwoWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"
              ItemsSource="{Binding Path=StateList, Mode=TwoWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}">
            <ComboBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="{Binding Path=Code}" />
                        <TextBlock Text="{Binding Path=Name}" Margin="5,0,0,0" />
                    </StackPanel>
                </DataTemplate>
            </ComboBox.ItemTemplate>
        </ComboBox>
    </Grid>
</UserControl>

这是我的StateSelector.xaml.cs

public class StateSelector : UserControl
{
    public ObservableCollection<State> StateList
    {
        get { return (ObservableCollection<State>)GetValue(StateListProperty); }
        set { SetValue(StateListProperty, value); }
    }
    public static readonly DependencyProperty StateListProperty =
        DependencyProperty.Register("StateList", typeof(ObservableCollection<State>), typeof(StateSelector));

    public State CurrentState
    {
        get{ return (State)GetValue(CurrentStateProperty); }
        set{ SetValue(CurrentStateProperty, value); }
    }
    public static DependencyProperty CurrentStateProperty =
        DependencyProperty.Register("CurrentState", typeof(State), typeof(StateSelector));

    /// <summary>
    /// Default constructor for StateSelector
    /// </summary>
    public StateSelector()
    {
        InitializeComponent();
    }
}

然后在包含UserControl的构造函数中,我使用State对象填充ObservableCollection。 这是MyDisplay.xaml.cs

public class MyDisplay : UserControl
{
    private static DependencyProperty StateListProperty =
        DependencyProperty.Register("StateList", typeof(ObservableCollection<State>), typeof(RateTableDisplay));
    public ObservableCollection<State> StateList
    {
        get{ return (ObservableCollection<State>)GetValue(StateListProperty); }
        set{ SetValue(StateListProperty, value); }
    }

    // Code to define SourceObject as seen in following XAML omitted

    public MyDisplay()
    {
        InitializeComponent();

        StateManager stateManager = new StateManager();
        StateList = new ObservableCollection<State>(stateManager.GetAll(Context));
    }
}

在MyDisplay的XAML中,我有一个部分,它按原样使用StateSelector,另一个部分在DataTemplate中使用它。 这是MyDisplay.xaml

<UserControl x:Class="MyNamespace.MyDisplay"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:System="clr-namespace:System;assembly=mscorlib"
    xmlns:Local="clr-namespace:MyNamespace"
    Height="Auto" Width="Auto"
    Name="_this"
    DataContext="{Binding ElementName=_this, Path=SourceObject}">

<UserControl.Resources>
    <ResourceDictionary>
        <DataTemplate x:Key="OriginStateCellTemplate">
            <Local:StateSelector StateList="{Binding ElementName=_this, Path=StateList}" />
        </DataTemplate>
    </ResourceDictionary>
</UserControl.Resources>

<!-- Unrelated XAML omitted -->
<!-- The StateSelector below gets populated properly -->
<StackPanel>
    <Local:StateSelector Grid.Column="3" StateList="{Binding ElementName=_this, Path=StateList}" x:Name="cmbMasterOriginState" />
</StackPanel>

<!-- More Unrelated XAML omitted -->
<!-- The StateSelector below does not get populated at all -->
<StackPanel>
    <ListView Height="610">
        <ListView.View>
            <GridView AllowsColumnReorder="False">
                <GridViewColumn x:Name="origStateCol" Width="85" CellTemplate="{StaticResource OriginStateCellTemplate}">
                    <GridViewColumnHeader Click="header_Click" Tag="OriginState">Origin State</GridViewColumnHeader>
                </GridViewColumn>
            </GridView> 
        </ListView.View>
    </ListView>
</StackPanel>
</UserControl>

我尝试过不同的方法来绑定StateList,例如:

StateList="{Binding Path=StateList, Source={x:Reference _this}}"
StateList="{Binding Path=StateList, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"

但没有这样的运气。我无法弄清楚为什么没有在DataTemplate示例中填充ItemsSource。它在DataTemplate之外工作正常。我在Visual Studio的调试输出中也没有遇到任何绑定错误。

搜索时我发现了很多相关问题,但他们似乎都在尝试使用顶级UserControl元素中定义的通用DataContext。我特意尝试使用UserControl本身的属性。

有什么想法吗?

1 个答案:

答案 0 :(得分:2)

INotifyPropertyChanged中实施UserControl,然后为StateList创建属性,然后在setter上提升INotifyPropertyChanged提供的属性更改事件。