简体   繁体   English

在代码后面指定UserControl的.XAML部分

[英]Specify .XAML part of UserControl in code-behind

I wrote custom TreeView control. 我编写了自定义TreeView控件。

XAML: 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 的.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();
    }
}

But when I try to use it I got well known error: 但是当我尝试使用它时,我得到了一个众所周知的错误:

Cannot set Name attribute value 'TextBox' on element 'TextBox'. 无法在元素“ TextBox”上设置“名称”属性值“ TextBox”。 'TextBox' is under the scope of element 'MyTreeView', which already had a name registered when it was defined in another scope. “文本框”在元素“ MyTreeView”的范围内,该元素在另一个范围中定义时已注册了名称。

I found some receipts how to fix this error. 我发现一些收据如何解决此错误。 Namely, specify .xaml part of control in its code-behind. 即,在其代码后面指定控件的.xaml部分。 But I have no idea how can I do this. 但是我不知道该怎么做。

The code clearly shows you want to extend TreeView. 该代码清楚地表明您要扩展TreeView。 Basically if you want to build control that can hold some content(which can be named...), like ContentControl, ItemsControl, etc.. it is always better to go with CustomControl. 基本上,如果您要构建可以容纳某些内容(可以命名为...)的控件,例如ContentControl,ItemsControl等,则最好使用CustomControl。 UserControl with XAML and CS code is not suitable for this case. 带有XAML和CS代码的UserControl不适合这种情况。

In your case, create a class like below and extend the functionalities, 就您而言,创建如下所示的类并扩展功能,

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();
    }
}

If you want to customize the look and feel, you should override the default Style of the control. 如果要自定义外观,则应覆盖控件的默认样式。 This style should be available in generic.xaml file inside Themes folder. 此样式应该在Themes文件夹内的generic.xaml文件中可用。 More information on Custom Control development is here . 有关自定义控件开发的更多信息在这里

     <Style TargetType="{x:Type TreeViewItem}">
        <Setter Property="IsExpanded"
                Value="{Binding IsExpanded, Mode=TwoWay}" />
        <Setter Property="IsSelected"
                Value="{Binding IsSelected, Mode=TwoWay}" />
    </Style>

I found solution appropriate for me. 我发现适合我的解决方案。 This it the way how to define Style of TreeViewItem in code, not in XAML . 这是如何在代码中而不是XAML定义TreeViewItem Style的方式。 Now I have TreeView definded only in code-behind, therefore, error will not be risen. 现在,我仅在后台代码中定义了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);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM