UserControl displaying several content properties! How interesting that would be!

I am trying to create a UserControl that we hope will be able to expose several content properties. However, I ride with a mistake!

The idea would be to create this great custom control (we will call it MultiContent ) that provides two content properties so that I can do the following:

    <local:MultiContent>
        <local:MultiContent.ListContent>
            <ListBox x:Name="lstListOfStuff" Width="50" Height="50" />                
        </local:MultiContent.ListContent>
        <local:MultiContent.ItemContent>
            <TextBox x:Name="txtItemName" Width="50" />
        </local:MultiContent.ItemContent>
    </local:MultiContent>

This would be very useful, now I can change the ListContent and ItemContent depending on the situation, with the general functionality included in the MultiContent user control.

However, the way I currently implemented cannot access the user interface elements inside these properties of the contents of the MultiContent control . For example, lstListOfStuff and txtItemName are null when I try to access them:

public MainPage() {
    InitializeComponent();
    this.txtItemName.Text = "Item 1"; // <-- txtItemName is null, so this throws an exception
}

This is how I implemented the MultiContent user control:

XAML: MultiContent.xaml

<UserControl x:Class="Example.MultiContent"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Width="400" Height="300">
    <Grid x:Name="LayoutRoot" Background="White">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="100" />
            <ColumnDefinition Width="100" />
        </Grid.ColumnDefinitions>
        <ContentControl x:Name="pnlList" Grid.Column="0" />
        <ContentControl x:Name="pnlItem" Grid.Column="1" />
    </Grid>
</UserControl>

Code for: MultiContent.xaml.cs

// Namespaces Removed
namespace Example
{
    public partial class MultiContent : UserControl
    {
        public UIElement ListContent
        {
            get { return (UIElement)GetValue(ListContentProperty); }
            set 
            {
                this.pnlList.Content = value;
                SetValue(ListContentProperty, value); 
            }
        }
        public static readonly DependencyProperty ListContentProperty =
            DependencyProperty.Register("ListContent", typeof(UIElement), typeof(MultiContent), new PropertyMetadata(null));

        public UIElement ItemContent
        {
            get { return (UIElement)GetValue(ItemContentProperty); }
            set 
            {
                this.pnlItem.Content = value;
                SetValue(ItemContentProperty, value); 
            }
        }
        public static readonly DependencyProperty ItemContentProperty =
            DependencyProperty.Register("ItemContent", typeof(UIElement), typeof(MultiContent), new PropertyMetadata(null));


        public MultiContent()
        {
            InitializeComponent();
        }
    }
}

I probably implement this completely wrong. Does anyone know how I can make this work correctly? How can I access these user interface elements by name from the parent control? Any suggestions on how to make this better? Thank!

+3
1

, .

UIElement - , null, NullReference. , null TextBox - , , .

Silverlight Dpendency. , . .

DP , . , , , , DP: ItemContent ListContent , Content (object), , , ! , :

MultiContent.xaml:

   <Grid x:Name="LayoutRoot" Background="White">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="100" />
            <ColumnDefinition Width="100" />
        </Grid.ColumnDefinitions>
        <ContentControl x:Name="pnlList" Grid.Column="0" />
        <ContentControl x:Name="pnlItem" Grid.Column="1" />
    </Grid>    

MultiContent.xaml.cs:

namespace MultiContent
{
    public partial class MultiContent : UserControl
    {
        #region ListContent

        /// <summary>
        /// ListContent Dependency Property
        /// </summary>
        public object ListContent
        {
            get { return (object)GetValue(ListContentProperty); }
            set { SetValue(ListContentProperty, value); }
        }
        /// <summary>
        /// Identifies the ListContent Dependency Property.
        /// </summary>
        public static readonly DependencyProperty ListContentProperty =
            DependencyProperty.Register("ListContent", typeof(object),
            typeof(MultiContent), new PropertyMetadata(null, OnListContentPropertyChanged));

        private static void OnListContentPropertyChanged
          (object sender, DependencyPropertyChangedEventArgs e)
        {
            MultiContent m = sender as MultiContent;
            m.OnPropertyChanged("ListContent");
        }

        #endregion

        #region ItemContent

        /// <summary>
        /// ItemContent Dependency Property
        /// </summary>
        public object ItemContent
        {
            get { return (object)GetValue(ItemContentProperty); }
            set { SetValue(ItemContentProperty, value); }
        }
        /// <summary>
        /// Identifies the ItemContent Dependency Property.
        /// </summary>
        public static readonly DependencyProperty ItemContentProperty =
            DependencyProperty.Register("ItemContent", typeof(object),
            typeof(MultiContent), new PropertyMetadata(null, OnItemContentPropertyChanged));

        private static void OnItemContentPropertyChanged
          (object sender, DependencyPropertyChangedEventArgs e)
        {
            MultiContent m = sender as MultiContent;
            m.OnPropertyChanged("ItemContent");
        }

        #endregion

        /// <summary>
        ///  Event called when any chart property changes
        ///  Note that this property is not used in the example but is good to have if you plan to extend the class!
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        ///  Called to invoke the property changed event
        /// </summary>
        /// <param name="propertyName">The property that has changed</param>
        protected void OnPropertyChanged(string propertyName)
        {
            if (propertyName == "ListContent")
            {
                // The ListContent property has been changed, let update the control!
                this.pnlList.Content = this.ListContent;
            }
            if (propertyName == "ItemContent")
            {
                // The ListContent property has been changed, let update the control!
                this.pnlItem.Content = this.ItemContent;
            }
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        public MultiContent()
        {
            InitializeComponent();
        }
    }
}

MainPage.xaml:

    <Grid x:Name="LayoutRoot" Background="White">
        <local:MultiContent>
            <local:MultiContent.ListContent>
                <ListBox x:Name="lstListOfStuff" Width="50" Height="50" />
            </local:MultiContent.ListContent>
            <local:MultiContent.ItemContent>
                <TextBox x:Name="txtItemName" Width="50" />
            </local:MultiContent.ItemContent>
        </local:MultiContent>
    </Grid>

!

+3

Source: https://habr.com/ru/post/1728525/


All Articles