在代码隐藏中指定 UserControl 的 .XAML 部分
Posted
技术标签:
【中文标题】在代码隐藏中指定 UserControl 的 .XAML 部分【英文标题】:Specify .XAML part of UserControl in code-behind 【发布时间】:2015-01-26 20:13:00 【问题描述】:我编写了自定义TreeView
控件。
XAML:
<TreeView x:Class="EArchiveMaster.View.MyTreeView"
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"
d:DesignHeight="300" d:DesignWidth="300">
<TreeView.ItemContainerStyle>
<Style TargetType="x:Type TreeViewItem">
<Setter Property="IsExpanded" Value="Binding IsExpanded, Mode=TwoWay" />
<Setter Property="IsSelected" Value="Binding IsSelected, Mode=TwoWay" />
<EventSetter Event="LostFocus" Handler="EventSetter_OnHandler" />
</Style>
</TreeView.ItemContainerStyle>
</TreeView>
.cs
public partial class MyTreeView
public event Action SomeItemLostFocus;
public MyTreeView()
InitializeComponent();
private void EventSetter_OnHandler(object sender, RoutedEventArgs e)
e.Handled = true;
if (SomeItemLostFocus != null)
SomeItemLostFocus();
但是当我尝试使用它时,我得到了众所周知的错误:
无法在元素“TextBox”上设置名称属性值“TextBox”。 “TextBox”在元素“MyTreeView”的范围内,当它在另一个范围内定义时,它已经注册了一个名称。
我找到了一些收据来解决这个错误。即,在其代码隐藏中指定控制的 .xaml 部分。 但我不知道我该怎么做。
【问题讨论】:
已经有一个相同的question for WPF。大多数答案也适用于您的情况。此外,您没有显示将Name
设置为TextBox
的位置。
@icebat 我将Name
设置为TextBox
的位置无关紧要。问题是“如何在其代码隐藏中指定控制的 .xaml 部分”。你能帮忙吗?
@icebat 我已经看到了这个问题,但我不明白在我的情况下我应该在OnInitialized
方法中写什么......
【参考方案1】:
代码清楚地表明您想要扩展 TreeView。基本上,如果您想构建可以保存一些内容(可以命名...)的控件,例如 ContentControl、ItemsControl 等。使用 CustomControl 总是更好。带有 XAML 和 CS 代码的 UserControl 不适合这种情况。
在您的情况下,创建一个如下所示的类并扩展功能,
public class MyTreeView : TreeView
public event Action SomeItemLostFocus;
public MyTreeView()
DefaultStyleKey = typeof(MyTreeView);
public override void OnLostFocus(object sender, RoutedEventArgs e)
e.Handled = true;
if (SomeItemLostFocus != null)
SomeItemLostFocus();
如果你想自定义外观,你应该覆盖控件的默认样式。此样式应在 Themes 文件夹内的 generic.xaml 文件中可用。有关自定义控件开发的更多信息是here。
<Style TargetType="x:Type TreeViewItem">
<Setter Property="IsExpanded"
Value="Binding IsExpanded, Mode=TwoWay" />
<Setter Property="IsSelected"
Value="Binding IsSelected, Mode=TwoWay" />
</Style>
【讨论】:
你看到问题了吗?因为,你几乎只是复制粘贴了我的代码 没有。您的代码是用户控件。我的代码是自定义控件。您的代码与 XAML 一起具有部分类。我的代码具有从 TreeView 扩展的独立类。我的代码不会抛出 NameScope 错误。 好的,但您的样式不包含<EventSetter Event="LostFocus" Handler="EventSetter_OnHandler" />
。这个字符串非常重要。如果Style
将与.cs 分开定义,我将无法使用EventSetter
,因为它需要事件处理程序。
您可以使用 OnLostFocus 覆盖方法,而不是使用 Eventhandler。
只是不明白你的OnLostFocus
方法将如何被调用,当TreeViewITEM
的LostFocus 事件将上升时。它们之间的联系在哪里?【参考方案2】:
我找到了适合我的解决方案。这就是如何在代码中而不是在 XAML
中定义 TreeViewItem
的 Style
的方式。现在我只在代码隐藏中定义了TreeView
,因此不会出现错误。
public class MyTreeView : TreeView
public event RoutedEventHandler ItemLostLogicFocus;
protected override void OnInitialized(EventArgs e)
base.OnInitialized(e);
var itemContainerStyle = new Style
TargetType = typeof(TreeViewItem),
;
#region Binding
var expandedBinding = new Binding("IsExpanded")
Mode = BindingMode.TwoWay,
;
var selectedBinding = new Binding("IsSelected")
Mode = BindingMode.TwoWay,
;
#endregion
#region Setters
itemContainerStyle.Setters.Add(new Setter
Property = TreeViewItem.IsExpandedProperty,
Value = expandedBinding
);
itemContainerStyle.Setters.Add(new Setter
Property = TreeViewItem.IsSelectedProperty,
Value = selectedBinding
);
#endregion
#region EventSetters
itemContainerStyle.Setters.Add(new EventSetter
Event = LostFocusEvent,
Handler = new RoutedEventHandler(ItemLostLogicFocusHandler)
);
#endregion
ItemContainerStyle = itemContainerStyle;
private void ItemLostLogicFocusHandler(Object sender, RoutedEventArgs e)
e.Handled = true;
if (ItemLostLogicFocus != null)
ItemLostLogicFocus(sender, e);
【讨论】:
以上是关于在代码隐藏中指定 UserControl 的 .XAML 部分的主要内容,如果未能解决你的问题,请参考以下文章
如何创建一个接受在 XAML 中添加子元素的 UserControl
用nodejs sequelize中指定的字段隐藏db中的一个结果。