• This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn more.

Exposing contained control properties from within a custom control

M

Martin Robins

#1
I am trying to create a custom control that can be used to present a common look and feel within my application. My first start is to try and create a basic dialog using the following xaml ...

<Style TargetType="{x:Type local:DialogBase}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:DialogBase}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<DockPanel Grid.Row="0" Margin="5">
<TabControl Name="PART_TabControl"/>
</DockPanel>

<DockPanel Grid.Row="1" LastChildFill="False" HorizontalAlignment="Right" Margin="5">
<Button IsDefault="True">OK</Button>
<Button IsCancel="True">Cancel</Button>
</DockPanel>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

I want to expose the Items property of the TabControl as the default property when I use this control so that I can use it like ...

<my:DialogBase ...>
<TabItem .../>
<TabItem.../>
</my:DialogBase>

I simply cannot work out how to do it (I am very new to WPF).

I have tried the following in code

namespace WpfCustomControlLibrary {
#region Namespace references
using System;
using System.Windows;
using System.Windows.Markup;
using System.Windows.Controls;
using System.ComponentModel;
using System.Windows.Input;
using System.Collections.ObjectModel;
#endregion
[DefaultProperty("Items"), ContentProperty("Items")]
public class DialogBase : Window {
#region Fields
private TabControl tabControl;
#endregion
#region Constructor
static DialogBase() {
DefaultStyleKeyProperty.OverrideMetadata(typeof(DialogBase), new FrameworkPropertyMetadata(typeof(DialogBase)));
}
#endregion
[Bindable(true), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public ItemCollection Items {
get { return this.tabControl.Items; }
}
#region Methods
public override void OnApplyTemplate() {
base.OnApplyTemplate();
this.tabControl = this.Template.FindName("PART_TabControl", this) as TabControl;
}
public Nullable<bool> ShowDialog(Window owner) {
this.Owner = owner;
return this.ShowDialog();
}
#endregion
}
}

But this fails because WPF attempts to merge the control xaml with the inner xaml before the OnApplyTemplate can work; therefore I end up with null reference exceptions because I cannot reference the tab control before the xaml is merged.

I am sure there is an easy way to do this but I cannot find it - and I have spent some considerable time on experiments and Google.

Anybody care to share?


Thanks


Martin.
 

My Computer

M

Martin Robins

#2
Please refer to my repost rather than answer on this thread. Sorry; I missed a group in this post so I have reposted.
"Martin Robins" <martin at orpheus-solutions dot co dot uk> wrote in message news:eo9CwoxmIHA.6064@xxxxxx
I am trying to create a custom control that can be used to present a common look and feel within my application. My first start is to try and create a basic dialog using the following xaml ...

<Style TargetType="{x:Type local:DialogBase}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:DialogBase}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<DockPanel Grid.Row="0" Margin="5">
<TabControl Name="PART_TabControl"/>
</DockPanel>

<DockPanel Grid.Row="1" LastChildFill="False" HorizontalAlignment="Right" Margin="5">
<Button IsDefault="True">OK</Button>
<Button IsCancel="True">Cancel</Button>
</DockPanel>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

I want to expose the Items property of the TabControl as the default property when I use this control so that I can use it like ...

<my:DialogBase ...>
<TabItem .../>
<TabItem.../>
</my:DialogBase>

I simply cannot work out how to do it (I am very new to WPF).

I have tried the following in code

namespace WpfCustomControlLibrary {
#region Namespace references
using System;
using System.Windows;
using System.Windows.Markup;
using System.Windows.Controls;
using System.ComponentModel;
using System.Windows.Input;
using System.Collections.ObjectModel;
#endregion
[DefaultProperty("Items"), ContentProperty("Items")]
public class DialogBase : Window {
#region Fields
private TabControl tabControl;
#endregion
#region Constructor
static DialogBase() {
DefaultStyleKeyProperty.OverrideMetadata(typeof(DialogBase), new FrameworkPropertyMetadata(typeof(DialogBase)));
}
#endregion
[Bindable(true), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public ItemCollection Items {
get { return this.tabControl.Items; }
}
#region Methods
public override void OnApplyTemplate() {
base.OnApplyTemplate();
this.tabControl = this.Template.FindName("PART_TabControl", this) as TabControl;
}
public Nullable<bool> ShowDialog(Window owner) {
this.Owner = owner;
return this.ShowDialog();
}
#endregion
}
}

But this fails because WPF attempts to merge the control xaml with the inner xaml before the OnApplyTemplate can work; therefore I end up with null reference exceptions because I cannot reference the tab control before the xaml is merged.

I am sure there is an easy way to do this but I cannot find it - and I have spent some considerable time on experiments and Google.

Anybody care to share?


Thanks


Martin.
 

My Computer