绑定到ObservableCollection的用户控件<frameworkelement>显示&#34;(收集)&#34; </frameworkelement>

时间:2015-02-25 16:47:39

标签: c# wpf xaml

我正在尝试构建一个名为“Screen”的WPF用户控件,它有两个附加属性,表现为内容插槽,用于显示控件集合和按钮集合。我的设计基于WPF: template or UserControl with 2 (or more!) ContentPresenters to present content in 'slots'找到的解决方案。

当我运行项目时,我希望看到我的“屏幕”控件,而不是在屏幕上看到字符串“(Collection)”。输出窗口中没有绑定错误。这是我的代码:

代码背后:

public partial class Screen : UserControl
{
    public Screen()
    {
        this.InitializeComponent();

        this.ScreenGrid.DataContext = this;
        this.DataContextChanged += this.ScreenDataContextChanged;
        this.Content = new ObservableCollection<FrameworkElement>();
        this.Buttons = new ObservableCollection<Button>();
    }

    private void ScreenDataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        if (this.GetValue(Screen.ScreenContentProperty) != null)
        {
            foreach (var control in ((ObservableCollection<FrameworkElement>)this.GetValue(Screen.ScreenContentProperty)))
            {
                control.DataContext = e.NewValue;
            }
        }

        if (this.GetValue(Screen.ButtonsProperty) != null)
        {
            foreach (var control in ((ObservableCollection<Button>)this.GetValue(Screen.ButtonsProperty)))
            {
                control.DataContext = e.NewValue;
            }
        }
    }

    public ObservableCollection<FrameworkElement> ScreenContent
    {
        get { return (ObservableCollection<FrameworkElement>)this.GetValue(Screen.ButtonsProperty); }
        set { this.SetValue(Screen.ScreenContentProperty, value); }
    }

    public ObservableCollection<Button> Buttons
    {
        get { return (ObservableCollection<Button>)this.GetValue(Screen.ButtonsProperty); }
        set { this.SetValue(Screen.ButtonsProperty, value); }
    }

    public static readonly DependencyProperty ScreenContentProperty = DependencyProperty.Register(
        "ScreenContent", typeof(ObservableCollection<FrameworkElement>), typeof(Screen),
        new PropertyMetadata(new ObservableCollection<FrameworkElement>()));

    public static readonly DependencyProperty ButtonsProperty = DependencyProperty.Register(
        "Buttons", typeof(ObservableCollection<Button>), typeof(Screen),
        new PropertyMetadata(new ObservableCollection<Button>()));
}

XAML:

<UserControl x:Class="Hca.Ims.Wpf.Views.Screen"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             mc:Ignorable="d">
    <StackPanel x:Name="ScreenGrid">
        <ItemsControl ItemsSource="{Binding ScreenContent}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <ContentPresenter Content="{TemplateBinding Content}" />
                </DataTemplate>
            </ItemsControl.ItemTemplate>
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <ScrollViewer>
                        <StackPanel />
                    </ScrollViewer>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
        </ItemsControl>
        <ItemsControl ItemsSource="{Binding Buttons}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <ContentPresenter Content="{TemplateBinding Content}" />
                </DataTemplate>
            </ItemsControl.ItemTemplate>
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <StackPanel />
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
        </ItemsControl>
    </StackPanel>
</UserControl>

用法:

<v:Screen>
    <v:Screen.ScreenContent>
        <TextBlock>Foo</TextBlock>
        <TextBlock>Bar</TextBlock>
    </v:Screen.ScreenContent>
    <v:Screen.Buttons>
        <Button>Submit</Button>
        <Button>Approve</Button>
    </v:Screen.Buttons>
</v:Screen>

任何想法我做错了什么?

1 个答案:

答案 0 :(得分:1)

您似乎拥有的代码多于实现此目的所需的代码。

将其归结为最简单的,您应该可以像这样使用基本的ItemsControl:

XAML

<UserControl x:Class="Hca.Ims.Wpf.Views.Screen"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             mc:Ignorable="d">
    <StackPanel x:Name="ScreenGrid">
        <ItemsControl ItemsSource="{Binding Items1}">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <StackPanel Orientation="Vertical"/>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
        </ItemsControl>        
    </StackPanel>
</UserControl>

代码隐藏:

public partial class Screen 
{
    public Screen()
    {
        InitializeComponent();

        ScreenGrid.DataContext = this;
        Items1 = new ObservableCollection<FrameworkElement>();
    }

    public static readonly DependencyProperty Items1Property = 
        DependencyProperty.Register("Items1", typeof(ObservableCollection<FrameworkElement>), typeof(Screen), new PropertyMetadata(null));

    public ObservableCollection<FrameworkElement> Items1
    {
        get { return (ObservableCollection<FrameworkElement>)GetValue(Items1Property); }
        set { SetValue(Items1Property, value); }
    }

}

用法:

    <v:Screen>
        <v:Screen.Items1>
            <TextBlock>Foo</TextBlock>
            <TextBlock>Bar</TextBlock>
            <Button><TextBlock Text="Button Text"/></Button>
        </v:Screen.Items1>
    </v:Screen>