我正在尝试创建一个UserControl,希望它能够公开多个内容属性。但是,我充满失败!
这个想法是创建一个很好的用户控件(我们将其称为MultiContent),该控件公开两个内容属性,以便我可以执行以下操作:
<local:MultiContent>
<local:MultiContent.ListContent>
<ListBox x:Name="lstListOfStuff" Width="50" Height="50" />
</local:MultiContent.ListContent>
<local:MultiContent.ItemContent>
<TextBox x:Name="txtItemName" Width="50" />
</local:MultiContent.ItemContent>
</local:MultiContent>
这将非常有用,现在我可以根据情况更改ListContent和ItemContent,并将常见功能分解为MultiContent用户控件。
但是,以我当前实现此方式的方式,我无法访问MultiContent控件的这些内容属性内的UI元素。例如,当我尝试访问它们时,lstListOfStuff和txtItemName都为null:
public MainPage() {
InitializeComponent();
this.txtItemName.Text = "Item 1"; // <-- txtItemName is null, so this throws an exception
}
这是我实现MultiContent用户控件的方式:
XAML:MultiContent.xaml
<UserControl x:Class="Example.MultiContent"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">
<Grid x:Name="LayoutRoot" Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
</Grid.ColumnDefinitions>
<ContentControl x:Name="pnlList" Grid.Column="0" />
<ContentControl x:Name="pnlItem" Grid.Column="1" />
</Grid>
</UserControl>
背后的代码:MultiContent.xaml.cs
// Namespaces Removed
namespace Example
{
public partial class MultiContent : UserControl
{
public UIElement ListContent
{
get { return (UIElement)GetValue(ListContentProperty); }
set
{
this.pnlList.Content = value;
SetValue(ListContentProperty, value);
}
}
public static readonly DependencyProperty ListContentProperty =
DependencyProperty.Register("ListContent", typeof(UIElement), typeof(MultiContent), new PropertyMetadata(null));
public UIElement ItemContent
{
get { return (UIElement)GetValue(ItemContentProperty); }
set
{
this.pnlItem.Content = value;
SetValue(ItemContentProperty, value);
}
}
public static readonly DependencyProperty ItemContentProperty =
DependencyProperty.Register("ItemContent", typeof(UIElement), typeof(MultiContent), new PropertyMetadata(null));
public MultiContent()
{
InitializeComponent();
}
}
}
我可能正在实施这完全错误的方法。有谁知道如何使它正常工作?如何从父控件按名称访问这些UI元素?关于如何做得更好的任何建议?谢谢!
最佳答案
您绝对可以实现自己的目标,但您需要采用其他方法。
在您的解决方案中,您尝试拥有UIElement的依赖项属性-且因为它从未设置且默认值为null,因此您将获得NullReference异常。您可以通过将默认值从null更改为新的TextBox或类似的方法继续进行,但是即使它确实起作用了,它仍然感觉像是被黑客入侵了。
在Silverlight中,您必须自己实现Dpendency属性。但是,您尚未实现它们,应该实现它们-我倾向于使用此dependency property generator来实现。
DP的一大优点是它们支持变更通知。因此,请记住,要使示例工作正常,所有要做的就是将DP定义为:与Content(对象)类型相同的ItemContent和ListContent,并且当框架通知您其中一个已更改时,只需更新您的文本框即可。 !因此,这是执行此操作的代码:
MultiContent.xaml:
<Grid x:Name="LayoutRoot" Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
</Grid.ColumnDefinitions>
<ContentControl x:Name="pnlList" Grid.Column="0" />
<ContentControl x:Name="pnlItem" Grid.Column="1" />
</Grid>
MultiContent.xaml.cs:
namespace MultiContent
{
public partial class MultiContent : UserControl
{
#region ListContent
/// <summary>
/// ListContent Dependency Property
/// </summary>
public object ListContent
{
get { return (object)GetValue(ListContentProperty); }
set { SetValue(ListContentProperty, value); }
}
/// <summary>
/// Identifies the ListContent Dependency Property.
/// </summary>
public static readonly DependencyProperty ListContentProperty =
DependencyProperty.Register("ListContent", typeof(object),
typeof(MultiContent), new PropertyMetadata(null, OnListContentPropertyChanged));
private static void OnListContentPropertyChanged
(object sender, DependencyPropertyChangedEventArgs e)
{
MultiContent m = sender as MultiContent;
m.OnPropertyChanged("ListContent");
}
#endregion
#region ItemContent
/// <summary>
/// ItemContent Dependency Property
/// </summary>
public object ItemContent
{
get { return (object)GetValue(ItemContentProperty); }
set { SetValue(ItemContentProperty, value); }
}
/// <summary>
/// Identifies the ItemContent Dependency Property.
/// </summary>
public static readonly DependencyProperty ItemContentProperty =
DependencyProperty.Register("ItemContent", typeof(object),
typeof(MultiContent), new PropertyMetadata(null, OnItemContentPropertyChanged));
private static void OnItemContentPropertyChanged
(object sender, DependencyPropertyChangedEventArgs e)
{
MultiContent m = sender as MultiContent;
m.OnPropertyChanged("ItemContent");
}
#endregion
/// <summary>
/// Event called when any chart property changes
/// Note that this property is not used in the example but is good to have if you plan to extend the class!
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Called to invoke the property changed event
/// </summary>
/// <param name="propertyName">The property that has changed</param>
protected void OnPropertyChanged(string propertyName)
{
if (propertyName == "ListContent")
{
// The ListContent property has been changed, let's update the control!
this.pnlList.Content = this.ListContent;
}
if (propertyName == "ItemContent")
{
// The ListContent property has been changed, let's update the control!
this.pnlItem.Content = this.ItemContent;
}
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public MultiContent()
{
InitializeComponent();
}
}
}
MainPage.xaml:
<Grid x:Name="LayoutRoot" Background="White">
<local:MultiContent>
<local:MultiContent.ListContent>
<ListBox x:Name="lstListOfStuff" Width="50" Height="50" />
</local:MultiContent.ListContent>
<local:MultiContent.ItemContent>
<TextBox x:Name="txtItemName" Width="50" />
</local:MultiContent.ItemContent>
</local:MultiContent>
</Grid>
这应该可以解决问题!
关于silverlight - UserControl公开多个内容属性!那将是多么令人兴奋!,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/2068125/