我正在尝试构建一个名为“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>
任何想法我做错了什么?
答案 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>