Wpf controls WPF中单选按钮的CustomContainer问题

Wpf controls WPF中单选按钮的CustomContainer问题,wpf-controls,custom-controls,radio-button,Wpf Controls,Custom Controls,Radio Button,我想创建一个只包含单选按钮的自定义控件。我设想它的用途如下: <RadioButtonHolder Orientation="Horizontal"> <RadioButton>RadioButton 1</RadioButton> <RadioButton>RadioButton 2</RadioButton> <RadioButton>RadioButton 3</RadioButton> <Radio

我想创建一个只包含单选按钮的自定义控件。我设想它的用途如下:

<RadioButtonHolder Orientation="Horizontal">
<RadioButton>RadioButton 1</RadioButton>
<RadioButton>RadioButton 2</RadioButton>
<RadioButton>RadioButton 3</RadioButton>
<RadioButton> ...</RadioButton>
</RadioButtonHolder>
RB1
RB2
将在
RBH1
中显示,
RB3
RB4
将在
RBH2
中显示为子项

我的代码如下:

<RadioButtonHolder Orientation="Horizontal">
<RadioButton>RadioButton 1</RadioButton>
<RadioButton>RadioButton 2</RadioButton>
<RadioButton>RadioButton 3</RadioButton>
<RadioButton> ...</RadioButton>
</RadioButtonHolder>
CustomControl.cs

using System.Collections.Generic;
using System.Windows;
using Sytem.Windows.Controls;
using System.Windows.Markup;

namespace RandomControl
{
[ContentProperty("Children")]
public class CustomControl1 : Control
{
   public static DependencyProperty ChildrenProperty = 
      DependencyProperty.Register("Children", typeof(List<RadioButton>),
      typeof(CustomControl1),new PropertyMetadata(new List<RadioButton>()));

   public List<RadioButton> Children
   {
       get { return (List<RadioButton>)GetValue(ChildrenProperty); }
       set { SetValue(ChildrenProperty, value); }
   }

    static CustomControl1()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomControl1), 
             new FrameworkPropertyMetadata(typeof(CustomControl1)));
    }
 }
}
using System.Collections.Generic;
using System.Windows;
using Sytem.Windows.Controls;
using System.Windows.Markup;

namespace RandomControl
{
    [ContentProperty("Children")]
    public class CustomControl1 : Control
    {
        private ObservableCollection<RadioButton> _children;
        private ItemsControl _control;

        public ObservableCollection<RadioButton> Children
        {
            get
            {
                if (_children == null)
                    _children = new ObservableCollection<RadioButton>();
                return _children;
            }
            private set { _children = value; }
        }

        static CustomControl1()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomControl1), 
             new FrameworkPropertyMetadata(typeof(CustomControl1)));
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            _control = base.GetTemplateChild("PART_ItemsControl") 
                            as ItemsControl;

            // display the radio buttons
            if (_control != null)
                _control.ItemsSource = Children;
        }
    }
}
使用System.Collections.Generic;
使用System.Windows;
使用Sytem.Windows.Controls;
使用System.Windows.Markup;
命名空间随机控件
{
[内容财产(“儿童”)]
公共类CustomControl1:控件
{
公共静态从属属性ChildrenProperty=
受抚养人财产登记簿(“子女”,类型(列表),
typeof(CustomControl1),新的PropertyMetadata(新列表());
公开儿童名单
{
获取{return(List)GetValue(ChildrenProperty);}
set{SetValue(ChildrenProperty,value);}
}
静态CustomControl1()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomControl1),
新的FrameworkPropertyMetadata(typeof(CustomControl1));
}
}
}
Generic.xaml

<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:RandomControl">
 <Style TargetType="{x:Type local:CustomControl1}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:CustomControl1}">
                <Border Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}">
                    <ItemsControl ItemsSource="{TemplateBinding Children}" 
                      Background="{TemplateBinding Background}">
                        <ItemsControl.ItemsPanel>
                            <ItemsPanelTemplate>
                                <StackPanel></StackPanel>
                            </ItemsPanelTemplate>
                        </ItemsControl.ItemsPanel>
                    </ItemsControl>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
 </Style>
</ResourceDictionary>
<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:RandomControl">
 <Style TargetType="{x:Type local:CustomControl1}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:CustomControl1}">
                <Border Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}">
                    <ItemsControl Name="PART_ItemControl"  
                      Background="{TemplateBinding Background}">
                        <ItemsControl.ItemsPanel>
                            <ItemsPanelTemplate>
                                <StackPanel></StackPanel>
                            </ItemsPanelTemplate>
                        </ItemsControl.ItemsPanel>
                    </ItemsControl>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
 </Style>
</ResourceDictionary>

WPF旨在尽可能简单地使用,但它也是非常新的,一开始就不那么容易获得

您只需要一个类似以下内容的xaml:

在窗口/页面/用户控件资源中添加

<Style x:Key="rbStyle" TargetType="RadioButton">
    <!--modify style to fit your needs-->
    <Setter Property="Margin" Value="2"/>
</Style>

<Style x:Key="rbStackPanelStyle" TargetType="StackPanel">
    <!--modify style to fit your needs-->
    <Setter Property="Orientation" Value="Vertical"/>
    <Setter Property="Margin" Value="2"/>
</Style>

然后在需要时声明您的“radioButtonHolder”:

<StackPanel x:Name="rbHolder1" Style="{StaticResource rbStackPanelStyle}">
    <RadioButton Style="{StaticResource rbStyle}">RadioButton 1</RadioButton>
    <RadioButton Style="{StaticResource rbStyle}">RadioButton 2</RadioButton>
    <RadioButton Style="{StaticResource rbStyle}">RadioButton 3</RadioButton>
    <RadioButton Style="{StaticResource rbStyle}">...</RadioButton>
</StackPanel>

单选按钮1
单选按钮2
单选按钮3
...
根据你的问题,这应该符合你的需要。不需要自定义控件。而且,许多进一步的修改可以适应其中的样式和模板


希望这有帮助,干杯。

我刚刚发现我做错了什么!它就在我面前,我没有看到它

这个问题的问题是我将
子对象设置为dependencProperty,这意味着它将是静态的和全局的。因此,整个
RadioButton
集合几乎可用于窗口中的所有控件。(事后来看,这可能就是StackPanel、Canvas等没有子属性作为从属属性的原因)。 您可以找到有关这方面的更多信息。

感谢kek444提供了一种更简单的方法:D

为了解决这个问题,您需要删除dependencProperty,并使用private
将子属性声明为普通属性

我已经修改了代码:

CustomControl.cs

using System.Collections.Generic;
using System.Windows;
using Sytem.Windows.Controls;
using System.Windows.Markup;

namespace RandomControl
{
[ContentProperty("Children")]
public class CustomControl1 : Control
{
   public static DependencyProperty ChildrenProperty = 
      DependencyProperty.Register("Children", typeof(List<RadioButton>),
      typeof(CustomControl1),new PropertyMetadata(new List<RadioButton>()));

   public List<RadioButton> Children
   {
       get { return (List<RadioButton>)GetValue(ChildrenProperty); }
       set { SetValue(ChildrenProperty, value); }
   }

    static CustomControl1()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomControl1), 
             new FrameworkPropertyMetadata(typeof(CustomControl1)));
    }
 }
}
using System.Collections.Generic;
using System.Windows;
using Sytem.Windows.Controls;
using System.Windows.Markup;

namespace RandomControl
{
    [ContentProperty("Children")]
    public class CustomControl1 : Control
    {
        private ObservableCollection<RadioButton> _children;
        private ItemsControl _control;

        public ObservableCollection<RadioButton> Children
        {
            get
            {
                if (_children == null)
                    _children = new ObservableCollection<RadioButton>();
                return _children;
            }
            private set { _children = value; }
        }

        static CustomControl1()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomControl1), 
             new FrameworkPropertyMetadata(typeof(CustomControl1)));
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            _control = base.GetTemplateChild("PART_ItemsControl") 
                            as ItemsControl;

            // display the radio buttons
            if (_control != null)
                _control.ItemsSource = Children;
        }
    }
}
使用System.Collections.Generic;
使用System.Windows;
使用Sytem.Windows.Controls;
使用System.Windows.Markup;
命名空间随机控件
{
[内容财产(“儿童”)]
公共类CustomControl1:控件
{
私人可观察收集儿童;
私有项控件_控件;
公众观察收集儿童
{
得到
{
if(_children==null)
_children=新的ObservableCollection();
返回儿童;
}
私有集{u children=value;}
}
静态CustomControl1()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomControl1),
新的FrameworkPropertyMetadata(typeof(CustomControl1));
}
应用程序模板()上的公共重写无效
{
base.OnApplyTemplate();
_control=base.GetTemplateChild(“PART\u ItemsControl”)
as ItemsControl;
//显示单选按钮
如果(_control!=null)
_control.ItemsSource=子项;
}
}
}
Generic.xaml

<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:RandomControl">
 <Style TargetType="{x:Type local:CustomControl1}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:CustomControl1}">
                <Border Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}">
                    <ItemsControl ItemsSource="{TemplateBinding Children}" 
                      Background="{TemplateBinding Background}">
                        <ItemsControl.ItemsPanel>
                            <ItemsPanelTemplate>
                                <StackPanel></StackPanel>
                            </ItemsPanelTemplate>
                        </ItemsControl.ItemsPanel>
                    </ItemsControl>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
 </Style>
</ResourceDictionary>
<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:RandomControl">
 <Style TargetType="{x:Type local:CustomControl1}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:CustomControl1}">
                <Border Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}">
                    <ItemsControl Name="PART_ItemControl"  
                      Background="{TemplateBinding Background}">
                        <ItemsControl.ItemsPanel>
                            <ItemsPanelTemplate>
                                <StackPanel></StackPanel>
                            </ItemsPanelTemplate>
                        </ItemsControl.ItemsPanel>
                    </ItemsControl>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
 </Style>
</ResourceDictionary>

谢谢你!:)这样做是有道理的。起初,我想让持有者做的是在单选按钮上覆盖一个墨水演示器,这样我就可以进行一些奇特的笔交互。