Click here to Skip to main content
15,943,477 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
Hello everyone,
I have a UserControl library containing the following usercontrol : DisplayGrid
XAML :
HTML
<UserControl x:Class="KelanicControls.DisplayGrid"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:local="clr-namespace:KelanicControls"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             x:Name="uc"
             d:DesignHeight="300"
             d:DesignWidth="300"
             Loaded="uc_Loaded"
             mc:Ignorable="d">

    <Grid x:Name="mainGrid">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="1*" />
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="1*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="1*" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="1*" />
        </Grid.RowDefinitions>
        <StackPanel Grid.Row="0"
                    Grid.ColumnSpan="3"
                    removed="{Binding ElementName=uc,
                                         Path=GridBackground}"
                    MouseLeftButtonUp="StackPanel_MouseLeftButtonUp"
                    Opacity="0.85" />
        <StackPanel Grid.Row="1"
                    removed="{Binding ElementName=uc,
                                         Path=GridBackground}"
                    MouseLeftButtonUp="StackPanel_MouseLeftButtonUp"
                    Opacity="0.85" />

        <Border x:Name="borderChildContainer"
                Grid.Row="1"
                Grid.Column="1" />

        <StackPanel Grid.Row="1"
                    Grid.Column="2"
                    removed="{Binding ElementName=uc,
                                         Path=GridBackground}"
                    MouseLeftButtonUp="StackPanel_MouseLeftButtonUp"
                    Opacity="0.85" />
        <StackPanel Grid.Row="2"
                    Grid.ColumnSpan="3"
                    removed="{Binding ElementName=uc,
                                         Path=GridBackground}"
                    MouseLeftButtonUp="StackPanel_MouseLeftButtonUp"
                    Opacity="0.85" />
    </Grid>
</UserControl>

Code :
C#
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace KelanicControls
{
    /// <summary>
    /// Interaction logic for DisplayGrid.xaml
    /// </summary>
    public partial class DisplayGrid : UserControl 
    {
        public DisplayGrid()
        {
            InitializeComponent();
        }
        public Brush GridBackground
        {
            get { return (Brush)GetValue(GridBackgroundProperty); }
            set { SetValue(GridBackgroundProperty, value); }
        }

        // Using a DependencyProperty as the backing store for GridBackground.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty GridBackgroundProperty =
            DependencyProperty.Register("GridBackground", typeof(Brush), typeof(DisplayGrid), new PropertyMetadata());


        public void SetChild(UIElement child)
        {
            InitializeComponent();
            Child = child;
            

        }
        public UIElement Child
        {
            get { return (UIElement)GetValue(ChildProperty); }
            set {
                SetValue(ChildProperty, value);
              

                borderChildContainer.Child = value;
                
            }
        }

        // Using a DependencyProperty as the backing store for Child.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ChildProperty =
            DependencyProperty.Register("Child", typeof(UIElement), typeof(DisplayGrid), new FrameworkPropertyMetadata(null , FrameworkPropertyMetadataOptions.AffectsParentMeasure));


        private void StackPanel_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            this.Visibility = Visibility.Collapsed;
        }

    
    }
}


when i use this usercontrol in another project like this :
HTML
 <kl:DisplayGrid Name="dg1" Gridremoved="DarkGreen">
   <kl:DisplayGrid.Child>
      <Button Content="click" />
   </kl:DisplayGrid.Child>
</kl:DisplayGrid>


The Problem is : setting the custom dependency propert "GridBackground" in XAML is reflected in the designer
but setting the "Child" property isn't
but setting it in the code behinde like this :
HTML
Button b = new Button() { Content = "Click" , Width=250 , Height=250};
dg1.SetChild(b);

does the trick

so why is this behavior ? and what am i doing wrong ?

What I have tried:

I have Tried setting the flag in the metadata of the child property to AffectsParentMeasure
and then to AffectsMeasure
with no avail
Posted
Updated 28-Apr-16 7:29am

1 solution

Hi,

the main problem here is that you try to do things in the set accessor for Child that it actually not called when accessed from XAML. Therefore, start by cleaning up the code-behind code by removing some lines:

C#
// !!! Suspect - never call InitializeComponent from anywhere but constructor
        //public void SetChild(UIElement child)
        //{
//InitializeComponent();
    //        Child = child;


  //      }
        public UIElement Child
        {
            get { return (UIElement)GetValue(ChildProperty); }
            set
            {
                SetValue(ChildProperty, value);

                // !!! Never do anything in a dependency accessor since it will not be called when used from XAML
                // borderChildContainer.Child = value;

            }
        }


Then, by using a ContentPresenter in your Border you can use the same approach as you seem to have used for GridBackground to bind the Child:

XML
<Border x:Name="borderChildContainer"
                Grid.Row="1"
                Grid.Column="1" >
            <ContentPresenter Content="{Binding Child, ElementName=uc}" />
        </Border>
 
Share this answer
 
v2
Comments
Ahmad_kelany 28-Apr-16 14:34pm    
works like a charm
thanks very much

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900