简体   繁体   English

在自定义UserControl上添加额外控件

[英]Add extra control on custom UserControl

I need to create custom UserControl so I can easily add some control so all control that implement CustomUserControl can affected. 我需要创建自定义UserControl,以便我可以轻松添加一些控件,以便实现CustomUserControl的所有控件都会受到影响。

This is what I do 这就是我的工作

public class CustomUserControl : UserControl
    {
        public CustomUserControl()
        {
            var stack = new StackPanel();
            stack.Children.Add(new TextBox() { Width = 100, Height = 100 });
            Content = stack; // need to add extra control to content
            //AddChild("test"); // this also fail
            //AddChild(stack); // this result in hard error
        }
    }

in the xaml 在xaml

<control:CustomUserControl x:Class="Sample"
             xmlns:control="clr-namespace:Sample.Controls;assembly=Sample"
             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">
    <Grid>
            <TextBox Width="100" Height="100"/>
    </Grid>
</control:CustomUserControl>

I want it to show 2 textbox, but it only show one, maybe because content overrided by parent. 我希望它显示2个文本框,但它只显示一个,可能是因为内容被父级覆盖。

Your constructor code is executing after XAML generation. 您的构造函数代码在XAML生成之后执行。 Your content first setting to "Grid" in XAML, then "Content = stack" in .cs file. 您的内容首先在XAML中设置为“网格”,然后在.cs文件中设置为“Content = stack”。 You need to set name to your grid in xaml and use it name in .cs file. 您需要在xaml中为网格设置名称,并在.cs文件中使用它的名称。 But don't do it, please, use MVVM. 但请不要这样做,请使用MVVM。

If you want a custom user control with two text boxes in it, just do that in the control's XAML: you don't need to do it in the constructor. 如果你想要一个带有两个文本框的自定义用户控件,只需在控件的XAML中执行:你不需要在构造函数中执行它。

In other words, delete your constructor: 换句话说,删除你的构造函数:

public class CustomUserControl : UserControl
{
}

and get rid of the Grid in the XAML: 并摆脱XAML中的Grid

<control:CustomUserControl x:Class="Sample" ... >
    <StackPanel>
        <TextBox Width="100" Height="100"/>
        <TextBox Width="100" Height="100"/>
    </StackPanel>
</control:CustomUserControl>

After digging UserControl and trial error I finally get what I want, just override on render in user control 在挖掘UserControl和试错后我终于得到了我想要的东西,只需在用户控件上覆盖渲染

protected override void OnRender(System.Windows.Media.DrawingContext drawingContext)
        {
            if (_group == null) //private field, hack so it only adding content once
            {
                var grid = new StackPanel() { Orientation = Orientation.Vertical };
                _group = new WarningBoxControl();

                var content = Content as StackPanel;
                if (content != null)
                {
                    _group.DataContext = content.DataContext;
                    content.Children.Insert(0, _group);
                }
            }

            base.OnRender(drawingContext);
        }

The only problem with this is Control that implement CustomUserControl must have stack panel at its root. 唯一的问题是控件,实现CustomUserControl的根目录必须有堆栈面板。 regardless this was easaier to maintain whenever I want to put extra control or something 无论何时我想要提供额外的控制或其他东西,这都是比较容易维护的

But if you want to add it from code you to give a name to the grid, then add childs from code. 但是如果你想从代码中添加它来为网格命名,那么从代码中添加子代码。 For example XAML: 例如XAML:

<UserControl x:Class="WpfApplication1.UserControl1"
         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">
<Grid x:Name="MyGrid">
    <Grid.RowDefinitions>
        <RowDefinition Height="29*"/>
        <RowDefinition Height="271*"/>
    </Grid.RowDefinitions>
    <TextBlock Text="TextBox1 Text" Grid.Row="0"/>
</Grid>

And .cs file will be: 而.cs文件将是:

public UserControl1()
    {
        InitializeComponent();
        var textBlock2 = new TextBlock();
        textBlock2.Text = "TextBox2 Text";
        MyGrid.Children.Add(textBlock2);
        Grid.SetRow(textBlock2,1);
    }
}

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

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