Проблемы с CustomContainer для радиокнопок в WPF - PullRequest
0 голосов
/ 19 июля 2009

Я хочу создать пользовательский элемент управления, который будет содержать только радиокнопки. Я представляю, как это используется следующим образом:

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

В настоящее время я создал пользовательский элемент управления, который частично делает это. Тем не менее, кажется, что эта коллекция RadioButton постоянно пополняется. И это добавило бы эту коллекцию RadioButtons к последнему инициализированному элементу управления. Кто-нибудь знает, почему это может быть? Любая помощь очень ценится.

Edit: Я вроде понял, что происходит в этом. Кажется, что когда объект инициализируется, он создаст список RadioButtons, который содержит все кнопки RadioButton, а затем присоединит его ко всем элементам управления RadioButtonHolder в окне как дочерние. И последний элемент управления отображает элементы.

Однако я не уверен, как это предотвратить, и локализую контент только для каждого элемента управления. Так что если бы я написал:

<RadioButtonHolder Name="RBH1">
<RadioButton Name="RB1">RB 1</RadioButton>
<RadioButton Name="RB2">RB 2</RadioButton>
</RadioButtonHolder>
<RadioButtonHolder Name="RBH2">
<RadioButton Name="RB3">RB 3</RadioButton>
<RadioButton Name="RB4">RB 4</RadioButton>
</RadioButtonHolder>

RB1 & RB2 будет отображаться в RBH1, а RB3 & RB4 будет отображаться как дочерний в RBH2.

Мой код выглядит следующим образом:

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

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>

Ответы [ 2 ]

0 голосов
/ 21 июля 2009

Я только что узнал, что я делаю неправильно! Это было прямо передо мной, и я этого не видел.

Проблема с этой проблемой заключалась в том, что Children было установлено как DependencyProperty - это означает, что оно будет статическим и глобальным. Таким образом, вся коллекция RadioButton была в значительной степени доступна для всех элементов управления в окне. (Оглядываясь назад, возможно, именно поэтому StackPanel, Canvas и т. Д. Не имеют свойства Children в качестве DependencyProperty). Вы можете найти больше информации об этом здесь .

Спасибо kek444 за публикацию более простого способа сделать это. : D

Чтобы исправить это, вам нужно удалить DependencyProperty и объявить Children как обычное свойство с приватным set.

Я изменил код:

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
    {
        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;
        }
    }
}

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 Name="PART_ItemControl"  
                      Background="{TemplateBinding Background}">
                        <ItemsControl.ItemsPanel>
                            <ItemsPanelTemplate>
                                <StackPanel></StackPanel>
                            </ItemsPanelTemplate>
                        </ItemsControl.ItemsPanel>
                    </ItemsControl>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
 </Style>
</ResourceDictionary>
0 голосов
/ 19 июля 2009

WPF призван быть максимально простым в использовании, но также очень новым и не таким простым для начала.

Все, что вам нужно, это что-то вроде xaml:

В вашем окне / странице / usercontrol Ресурсы добавьте

<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>

И это должно соответствовать вашим потребностям, в зависимости от вашего вопроса. Там нет необходимости для пользовательского элемента управления. И многие другие модификации могут быть встроены в стили и шаблоны в них.

Надеюсь, это было полезно, ура.

...