UserControl navigate in owning window wpf - wpf

In XAML/WPF I have main window which contains Frame where I intend to put one of the user controls for given view of application.
<Window x:Class="MyApp.MainWindow"
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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ignore="http://www.galasoft.ch/ignore"
mc:Ignorable="d ignore"
DataContext="{Binding Main, Source={StaticResource Locator}}">
<Grid x:Name="LayoutRoot">
<Frame Source="Main/MainUserControl.xaml" Name="Main" />
</Grid>
</Window>
Now I want to navigate this Frame to other source inside MainUserControl:
<UserControl x:Class="MyApp.View.MainMenu.MainMenuUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:lex="http://wpflocalizeextension.codeplex.com"
xmlns:command="clr-namespace:MyApp.Command"
mc:Ignorable="d"
Style="{StaticResource Localizable}"
DataContext="{Binding MainMenu, Source={StaticResource Locator}}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<Button Content="{lex:Loc About}" FontSize="28" Grid.Row="1" Command="NavigationCommands.GoToPage" CommandParameter="/Menu/AboutUserControl.xaml" />
</Grid>
</UserControl>
But the navigation button About remains inactive during execution. I verified correctly that /Menu/AboutUserControl.xaml exists.
I'm obviously doing something wrong. How can I navigate owning window's frame from within user control? Preferably via XAML?

I assume you are using an MVVM framework. (I have added the critical elements here in case you aren't).
Your MainWindow.xaml should use an "ItemsControl" instead of a "Frame". A frame can work, but a better way is to use the ItemsControl like so:
<!-- Main Frame -->
<Grid Grid.Column="1" Margin="10" Name="MainWindowFrameContent">
<ItemsControl ItemsSource="{Binding Path=MainWindowFrameContent}" >
<!-- This controls the height automatically of the user control -->
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="1" IsItemsHost="True"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Grid>
In the constructor of my MainWindow.cs, I set the DataContext of the window to the MainViewModel:
using myProject.ViewModel;
public partial class MainWindow : Window
{
MainViewModel mMainViewModel;
public MainWindow()
{
InitializeComponent();
// Initialize MainViewModel and set data context to the VM
mMainViewModel = new MainViewModel();
DataContext = mMainViewModel;
}
}
(I'm not sure if this next part HAS TO be an observable collection, but I have implemented it as such and it seems to work well. The only downside is that I need to manually clear the ItemsControl before adding a new UserControl)
My MainViewModel implements the binding called "MainWindowFrameContent". All of my user controls are initialized within the MainViewModel.cs code. I have an additional ViewModel for each UserControl and assign the DataContext of the UserControl to the individual ViewModel before displaying the UserControl to the main window.
My MainViewModel.cs:
public class MainViewModel : ObservableObject
{
public MainViewModel()
{
}
// This handles adding framework (UI) elements to the main window frame
ObservableCollection<FrameworkElement> _MainWindowFrameContent = new ObservableCollection<FrameworkElement>();
public ObservableCollection<FrameworkElement> MainWindowFrameContent
{
get
{
return _MainWindowFrameContent;
}
set
{
_MainWindowFrameContent = value;
RaisePropertyChangedEvent("MainWindowFrameContent");
}
}
// This handles opening a generic user control on the main window
// The ICommand implementation allows me to bind the command of a button on the main window to displaying a specific page
public ICommand MainWindowDataEntryView
{
get
{
return new DelegateCommand(_MainWindowDataEntryView);
}
}
void _MainWindowDataEntryView(object obj)
{
DataEntryVM wDataEntryVM = new DataEntryVM();
DataEntryView wDataEntryView = new DataEntryView();
wDataEntryView.DataContext = wDataEntryVM;
MainWindowFrameContent.Clear();
MainWindowFrameContent.Add(wDataEntryView);
}
}
Then you need to make sure you have an ObservableObject.cs as part of your project:
using System.ComponentModel;
public class ObservableObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChangedEvent(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
And you need a DelegateCommand.cs class as part of your project:
using System;
using System.Windows.Input;
public class DelegateCommand : ICommand
{
private readonly Action<object> _action;
public DelegateCommand(Action<object> action)
{
_action = action;
}
public void Execute(object parameter)
{
_action(parameter);
}
public bool CanExecute(object parameter)
{
return true;
}
#pragma warning disable 67
public event EventHandler CanExecuteChanged { add { } remove { } }
#pragma warning restore 67
}
So, it's a bit of a lengthy explanation, but once you have the previous items set up, you can add a bunch of buttons to your MainWindow.xaml, bind each button to a command that adds a new UserControl to your ItemsControl. When your UserControl displays, you can add controls as you would like and use them.
I hope this helps!

Related

WPF page fixed layout with MVVM

I have a WPF application with MVVM that have several pages with common layout e.g. page header and navigation buttons (the middle part of each page is different).
How can I implement the fixed page layout once and extend it in the different pages with MVVM?
In my opinion, the best way to do this is to create a main window or page and then render user controls inside of that using a content control and data templates. Set the content control binding to a property on the main window's view model. You'll need an implementation of INotifyPropertyChanged, of course, then a main window or application view model, some child view models, a content control in your main window or page, then user controls to represent your views...sort of this this:
public abstract class ObservableObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string property)
{
PropertyChangedEventHandler handler = this.PropertyChanged;
if(handler != null)
{
handler(this, new PropertyChangedEventArgs(property));
}
}
[Conditional("DEBUG")]
[DebuggerStepThrough]
protected virtual void VerifyPropertyName(string property)
{
if (TypeDescriptor.GetProperties(this)[property] == null)
{
throw new Exception(property + " property doesn't exist!");
}
}
}
public interface IPageViewModel
{
string Name { get; }
}
public class Page1ViewModel : ObservableObject, IPageViewModel
{
public string Name { get { return "View 1"; } }
}
public class Page2ViewModel : ObservableObject, IPageViewModel
{
public string Name { get { return "View 1"; } }
}
public class ApplicationViewModel : ObservableObject
{
private IPageViewModel currentViewModel;
public IPageViewModel CurrentViewModel
{
get
{
return this.currentViewModel =
this.currentViewModel
?? new Page1ViewModel();
}
set
{
this.currentViewModel = value;
OnPropertyChanged("CurrentViewModel");
}
}
public ApplicationViewModel()
{
this.CurrentViewModel = new Page1ViewModel()
}
}
Your main window or page would have its view model (DataContext) set to an instance of ApplicationViewModel. The content control would then be bound to the CurrentViewModel property of the ApplicationViewModel, like this:
<Window x:Class="WpfScratchApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:app="clr-namespace:WpfScratchApp"
Title="MainWindow" Height="350" Width="525"
DataContext="{DynamicResource AppViewModel}"
>
<Window.Resources>
<ResourceDictionary>
<app:ApplicationViewModel x:Key="AppViewModel" />
</ResourceDictionary>
</Window.Resources>
<Grid>
<!-- Buttons and stuff -->
<ContentControl Content="{Binding CurrentViewModel}" />
</Grid>
</Window>
Then, create UserControl's corresponding to each of those views:
<UserControl x:Class="WpfScratchApp.Views.Page1View"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="150" d:DesignWidth="150">
<!-- Cool controls and stuff in here... -->
</UserControl>
(Create a similar one corresponding to Page2ViewModel, called "Page2View".) Then, map the view models to the views like this in your app.xaml, or a merged dictionary.
<Application x:Class="WpfScratchApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:views="clr-namespace:PortfolioManager"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<DataTemplate DataType="{x:Type vm:Page1ViewModel}">
<views:Page1View />
</DataTemplate>
<DataTemplate DataType="{x:Type vm:Page2ViewModel}">
<views:Page2View />
</DataTemplate>
</ResourceDictionary>
</Application.Resources>
</Application>
When you change the CurrentViewModel property in the application view model, it should change the value of the binding for the control control. WPF will use the data template corresponding to the type represented by the CurrentViewModel property to render the content.
So, you can have your buttons all set up in the main window and coded to operate on the CurrentViewModel. Then, change out the CurrentViewModel based upon the content you want to show.

Performance UserControl / CustomControl

I already searched a lot of sites on the net, but didn't find any solution. The statement is, that there is no performance difference between a UserControl and a CustomControl.
But I have the following test class X, UserControl, CustomControl and MainWindow:
public class X : INotifyPropertyChanged
{
private string _title;
public string Title
{
get
{
return _title;
}
set
{
if (value == _title)
{
return;
}
_title = value;
OnPropertyChanged("Title");
}
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
UserControl:
<UserControl x:Class="controlperformance.DisplayView"
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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006">
<Grid Name="root" Background="LightGray">
<TextBlock Text="{Binding Title}" />
</Grid>
</UserControl>
CustomControl:
public class DisplayControl : Control
{
#region Title
public string Title
{
get
{
return (string)GetValue(TitleProperty);
}
set
{
SetValue(TitleProperty, value);
}
}
public static readonly DependencyProperty TitleProperty = DependencyProperty.Register("Title",
typeof(string),
typeof(DisplayControl),
new PropertyMetadata(default(string)));
#endregion
static DisplayControl()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(DisplayControl), new FrameworkPropertyMetadata(typeof(DisplayControl)));
}
}
Xaml:
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:DisplayControl}">
<Grid Background="white">
<TextBlock Text="{TemplateBinding Title}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
MainWindow:
public partial class MainWindow : Window
{
Stopwatch sw = new Stopwatch();
public MainWindow()
{
InitializeComponent();
Loaded += OnLoaded;
sw.Start();
ObservableCollection<X> list = new ObservableCollection<X>();
Random r = new Random();
for (int i = 0; i < 50000; i++)
{
list.Add(new X { Title = r.Next().ToString()});
}
itemscontrol.ItemsSource = list;
}
private void OnLoaded(object sender, RoutedEventArgs routedEventArgs)
{
sw.Stop();
MessageBox.Show(sw.Elapsed.ToString());
}
}
MainWindow Content:
<ItemsControl Name="itemscontrol">
<ItemsControl.ItemTemplate>
<!--<DataTemplate DataType="{x:Type Controlperformance:X}">
<Controlperformance:DisplayView DataContext="{Binding}" />
</DataTemplate>-->
<DataTemplate DataType="{x:Type Controlperformance:X}">
<Controlperformance:DisplayControl Title="{Binding Title}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
When using the CustomControl, the MessageBox shows approx. 20 Seconds on my computer, but when using the UserControl, it takes about a minute! Replacing the Control with its Grid an TextBox, it is even faster than the CustomControl (~16 sec).
Can someone see where the bottleneck is? The problem raises in my real-world application, where the Template/Control would be much more complex.
Thanks a lot,
micro
This is a late answer but the basic difference is that a User Control is almost like a window in that you have the the control itself and then other controls like, buttons, grids, textboxes, etc can be added to it. The basic difference between a window and User Control is that the User Control can and must be displayed within a window.
A Custom Control on the other hand is just a control, it can be used to create a control with a specific functionality for which there are no built in controls or to give an existing control, like buttons, textboxes, etc a specific style to match the theme of your application. You can also add in extra features to existing controls by using a custom control such as adding a label to a text box to show it's purpose.
The difference in loading time is essentially a reflection of the different purposes of User and Custom Controls, with a User Control it load the control and the elements within that control so the loading time may be longer. With a Custom Control only the control itself must load so the so it won't take any longer to load than most built in WPF controls i.e. a button Custom Control shouldn't take longer than a built in button control.

How to close a TabItem in MVVM Light

In my view i'm adding dynamically custom TabItems (TextseiteTabItem). With the property DataContext i gave each TabItem a Model to work with (fill in values). Now i added a close-command to the custom TabItems but it wont work. I cant manage to send the close-command to the viewmodel. Above is my attempt..
My custom TabItem:
<sdk:TabItem x:Class="PortfolioCreator.TextseiteTabItem"
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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit">
<sdk:TabItem.Header>
<StackPanel Orientation="Horizontal">
<sdk:Label Content="{Binding Seitennummer, StringFormat='Seite {0}', Mode=TwoWay}"/>
<Button Content="X"
Command="{Binding CloseTabCommand, Mode=TwoWay}"
DataContext="{Binding ElementName=TemplateTabControl}"
CommandParameter="{Binding SelectedItem, ElementName=TemplateTabControl}" />
</StackPanel>
</sdk:TabItem.Header>
<sdk:TabItem.Content>
<Grid x:Name="LayoutRoot">
...
</Grid>
</sdk:TabItem.Content>
</sdk:TabItem>
In my View:
...
<sdk:TabControl toolkit:DockPanel.Dock="Bottom" ItemsSource="{Binding Tabs}" x:Name="TemplateTabControl"/>
...
In my ViewModel:
public class PortfolioViewModel : ViewModelBase
{
public ObservableCollection<TabItem> Tabs { get; set; }
public RelayCommand<TabItem> CloseTabCommand
{
get;
private set;
}
public PortfolioViewModel()
{
CloseTabCommand = new RelayCommand<TabItem>(tab =>
{
//never reached
},
tab =>
{
//never reached
});
Tabs = new ObservableCollection<TabItem>();
AddTextseite();
AddTextseite();
}
void AddTextseite()
{
TabItem item = new TextseiteTabItem();
item.DataContext = new TextSeiteModel();
Tabs.Add(item);
}
}
First, your CloseTabCommand does nothing in your current code snippet: //never reached. The execute handler should read something like tab.Visibility = Visibility.Collapsed or myTabControl.Items.Remove(myTabItem).
Second, as #Rafal pointed out, using UI elements in the ViewModel is not the correct way to implement MVVM. If you want closable tab items, the correct way would be to derive a generic CloseableTabItem control or write a ClosableTabItemBehavior on the UI layer with a settable ICommand CloseCommand that can be bound to the corresponding ICommand instance on the ViewModel. Admittedly this approach might be too elaborate for your project though.
You are attempting to use MVVM but the strange thing I see is collection of ui elements (Tabs) in your view model. The correct way would be to create ViewModel that describes Tab item and move the command there. Then it will bind. To remove tab from Tabs you should expose event in your Tab view model and attach to it form PortfolioViewModel.
Of course my change will cause that your TextseiteTabItem will not show in TablControl. But it can be easily fixed with TabControl.ItemTemplate and TabControl.ContentTemplate.
here you find a demo application with closeable tabs for wpf, maybe it works for your silverlight version also.
This is my workaround for this problem. I admit it is not a good solution and breaks the mvvm pattern but as #herzmeister says other approaches are too elaborate for my project right now. (But it won't be the final solution ;-) )
TabItemViewModel:
public delegate void CloseTabItemHandler();
public class TextseiteTabItemViewModel : ViewModelBase
{
public event CloseTabItemHandler CloseTabItem;
public RelayCommand CloseTabCommand {get; set;}
public TextseiteTabItemViewModel()
{
CloseTabCommand = new RelayCommand(() =>
{
if (CloseTabItem == null) return;
CloseTabItem();
});
}
}
TabItemView:
<sdk:TabItem x:Class="PortfolioCreator.TextseiteTabItemView"
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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit">
<sdk:TabItem.Header>
<StackPanel Orientation="Horizontal">
<Button Content="X" Command="{Binding CloseTabCommand, Mode=TwoWay}" />
</StackPanel>
</sdk:TabItem.Header>
<sdk:TabItem.Content>
<Grid x:Name="LayoutRoot">
...
</Grid>
</sdk:TabItem.Content>
</sdk:TabItem>
Parent ViewModel:
public class PortfolioViewModel : ViewModelBase
{
public ObservableCollection<TabItem> Tabs { get; set; }
public PortfolioViewModel()
{
Tabs = new ObservableCollection<TabItem>();
AddTextseite();
AddTextseite();
}
void AddTextseite()
{
var viewmodel = new TextseiteTabItemViewModel();
TabItem item = new TextseiteTabItemView();
item.DataContext = viewmodel;
viewmodel.CloseTabItem += new CloseTabItemHandler(() =>
{
Tabs.Remove(item);
});
Tabs.Add(item);
}
}

Invoke Command Within Custom User Control

I'm new to WPF and i'm trying to learn the famous MVVM pattern,
I'm facing a small issue (i'm sure) when i try to bind simple command to some ViewModel
this is Simple UserControl i've created:
<UserControl x:Class="MVVM_UsingUserControl_Sample.View.MyUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
>
<StackPanel DataContext="MyUserControlViewModel" Orientation="Vertical" >
<Button Margin="0,100,0,0" Height="50" Width="50" Content="PressMe" Command="{Binding Path=MyCommand}"/>
</StackPanel>
</UserControl>
and this is the User Control ViewModel
class MyUserControlViewModel : ViewModelBase
{
CommandBase m_MyCommand = null;
public MyUserControlViewModel()
{
}
public ICommand MyCommand
{
get
{
if (m_MyCommand == null)
{
m_MyCommand = new CommandBase(new Action<object>(DoSomething),
new Predicate<object>(CanDoSomething));
}
return m_MyCommand;
}
}
public void DoSomething(object i_Params)
{
MessageBox.Show("Inside MyUserControl DoSomething");
}
public bool CanDoSomething(object i_Params)
{
return true;
}
}
this is the Main window xaml (no code behaind)
Now the problem is :
My main window contains the userControl as is (inside stack panel) and nothing else.
i expect the command "MyCommad" will get invoke when i press the button "MyButton"
but it doesn't.
anyone has idea why ???
Big thanks.
In the constructor of your main window, set its DataContext to your ViewModel.
For example,
this.DataContext = new MyViewModel();
In your XAML, remove
DataContext="MyUserControlViewModel"
since the DataContext will inherit from the main window.
Everything should then work as you expect.

How to access a named element of a derived user control in silverlight?

I have a custom base user control in silverlight.
<UserControl x:Class="Problemo.MyBaseControl"
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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<Grid x:Name="LayoutRoot" Background="White">
<Border Name="HeaderControl" Background="Red" />
</Grid>
</UserControl>
With the following code behind
public partial class MyBaseControl : UserControl
{
public UIElement Header { get; set; }
public MyBaseControl()
{
InitializeComponent();
Loaded += MyBaseControl_Loaded;
}
void MyBaseControl_Loaded(object sender, RoutedEventArgs e)
{
HeaderControl.Child = Header;
}
}
I have a derived control.
<me:MyBaseControl x:Class="Problemo.MyControl"
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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:me="clr-namespace:Problemo"
d:DesignHeight="300" d:DesignWidth="400">
<me:MyBaseControl.Header>
<TextBlock Name="header" Text="{Binding Text}" />
</me:MyBaseControl.Header>
</me:MyBaseControl>
With the following code behind.
public partial class MyControl : MyBaseControl
{
public string Text
{
get; set;
}
public MyControl(string text)
{
InitializeComponent();
Text = text;
}
}
I'm trying to set the text value of the header textblock in the derived control.
It would be nice to be able to set both ways, i.e. with databinding or in the derived control code behind, but neither work. With the data binding, it doesn't work. If I try in the code behind I get a null reference to 'header'. This is silverlight 4 (not sure if that makes a difference)
Any suggestions on how to do with with both databinding and in code ?
Cheers
First of all I'll show you how to adjust your Derived control to handle this. You need to do two things, first you need to implement INotifyPropertyChanged and secondly you to add the binding to the user control.
MyControl Xaml:-
<me:MyBaseControl.Header>
<TextBlock Name="headerItem" />
</me:MyBaseControl.Header>
MyControl code:-
public partial class MyControl : MyBaseControl, INotifyPropertyChanged
{
public MyControl ()
{
InitializeComponent();
headerItem.SetBinding(TextBlock.TextProperty, new Binding("Text") { Source = this });
}
string _text;
public string Text
{
get { return _text; }
set { _text = value; NotifyPropertyChanged("Text"); }
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
void NotifyPropertyChanged(string name)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
#endregion
}
This should get you working. However, as soon as you feel you need to inherit a UserControl based class you should take a step back and ask whether the base and derived items ought to be templated controls instead. If I get time I'll try to add a version of your code in terms of templated controls.

Resources