Usercontrol as datatemplate with bindings - c#

I have an ItemsControl with ItemsSource binded to a list of SystemModels. It has to generate an usercontrol for every system in the list. And in those usercontrols it has some textboxes that show the name, is and location of the system.
My code creates the usercontrols but doesn't fill the textboxes in the usercontrol.
View:
<UserControl x:Name="SystemListScreen">
<ScrollViewer Grid.Row="1">
<ItemsControl x:Name="SystemList" ItemsSource="{Binding Path=Systems}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="4"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="SystemModel">
<Widgets:MultiLineButton partID="{Binding ID}"
company="{Binding ItemsSource.Company}"
typeSorter="{Binding ItemsSource.Name, ElementName=SystemList}"
typeLocation="{Binding ItemsSource.Location, ElementName=SystemList}"
buttonCommand="{Binding DataContext.navigateInspectList, ElementName=SystemListScreen}"
buttonCommandParameter="{Binding ItemsSource.ID, ElementName=SystemList}"/>
<!--<Button Content="{Binding ID}"/>-->
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</UserControl>
ViewModel:
private List<SystemModel> systems;
public SystemListViewModel()
{
Systems = new List<SystemModel>();
Systems = SystemAPI.Instance.GetSystems();
}
public string App { get; set; }
public List<SystemModel> Systems
{
get { return systems; }
private set
{
systems = value;
NotifyChanged("systems");
NotifyChanged("NoResultsFound");
}
}
multilinebutton code:
public static readonly DependencyProperty buttonCommandProperty = DependencyProperty.Register("buttonCommand", typeof(ICommand), typeof(MultiLineButton));
public static readonly DependencyProperty buttonCommandParameterProperty = DependencyProperty.Register("buttonCommandParameter", typeof(Object), typeof(MultiLineButton));
public static readonly DependencyProperty partIDProperty = DependencyProperty.Register("partID", typeof(String), typeof(MultiLineButton));
public static readonly DependencyProperty companyProperty = DependencyProperty.Register("company", typeof(String), typeof(MultiLineButton));
public static readonly DependencyProperty typeSorterProperty = DependencyProperty.Register("typeSorter", typeof(String), typeof(MultiLineButton));
public static readonly DependencyProperty typeLocationProperty = DependencyProperty.Register("typeLocation", typeof(String), typeof(MultiLineButton));
public MultiLineButton()
{
this.DataContext = this;
InitializeComponent();
}
public String partID
{
get { return (String)GetValue(partIDProperty); }
set { SetValue(partIDProperty, value); }
}
public String company
{
get { return (String)GetValue(companyProperty); }
set { SetValue(companyProperty, value); }
}
public String typeSorter
{
get { return (String)GetValue(typeSorterProperty); }
set { SetValue(typeSorterProperty, value); }
}
public String typeLocation
{
get { return (String)GetValue(typeLocationProperty); }
set { SetValue(typeLocationProperty, value); }
}
public ICommand buttonCommand
{
get { return (ICommand)GetValue(buttonCommandProperty); }
set { SetValue(buttonCommandProperty, value); }
}
public Object buttonCommandParameter
{
get { return (Object)GetValue(buttonCommandParameterProperty); }
set { SetValue(buttonCommandParameterProperty, value); }
}
what not works: partID="{Binding ID}", company="{Binding ItemsSource.Company}", typeSorter="{Binding ItemsSource.Name, ElementName=SystemList}", typeLocation="{Binding ItemsSource.Location, ElementName=SystemList}" and buttonCommandParameter="{Binding ItemsSource.ID, ElementName=SystemList}".
But if i use just a button as datatemplate with Content="{Binding ID}" It works Perfect, an d if i use the usercontrol outside the datatemplate it works also. But it will not work inside the datatemplate.
The error i get is this: "BindingExpression path error: 'Company' property not found on 'object' ''MultiLineButton' (Name='')'. BindingExpression:Path=Company; DataItem='MultiLineButton' (Name=''); target element is 'MultiLineButton' (Name=''); target property is 'company' (type 'String')"
How can i fix those bindings?

not sure, maybe you should remove DataType="SystemModel" from DateTemplate.
Or try to use simple textbox(Binding id) as DataTemplate, see if there is still empty.
If above didn't get you any help, try Snoop(snoopwpf.codeplex.com) see what happended.

try ObservableCollection:
private ObservableCollection<SystemModel> _systems = new ObservableCollection<SystemModel>();
public ObservableCollection<SystemModel> Systems { get { return _systems; } }
public SystemListViewModel()
{
var systems = SystemAPI.Instance.GetSystems();
foreach (var system in systems)
{
Systems.Add(system);
}
}
and xaml should be:
<UserControl x:Name="SystemListScreen">
<ScrollViewer Grid.Row="1">
<ItemsControl x:Name="SystemList" ItemsSource="{Binding Path=Systems}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="4"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Widgets:MultiLineButton
partID="{Binding ID}"
company="{Binding Company}"
typeSorter="{Binding Name}"
typeLocation="{Binding Location}"
buttonCommand="{Binding DataContext.navigateInspectList,
ElementName=SystemListScreen}"
buttonCommandParameter="{Binding ItemsSource.ID,
ElementName=SystemList}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</UserControl>
As chao wang said:
remove DataType="SystemModel" because if you're using just one type of DataType as DataTemplate it's not necessary. and the correct syntax is DataType="vm:SystemModel" where vm is defined in a parent tag like : xmlns:vm="clr-namespace:MySolution.MyVmProject.MyFolder"
also, check these:
remove ItemsSource. from Bindings inside DataTemplate because it's just wrong.
double check all names in bindings because if they're wrong, a null value is considered during runtime and you never know.
check your dataContext make sure UserControl have its DataContext to the correct instance of type dependency object which has Systems in it. and make sure it remains that way.

Related

UserControl's PropertyChangedCallback doesn't run

I have got an usercontrol with some dependency property. One of them (ValueProperty) has got a PropertyChangedCallback but it never run.
namespace test
{
public partial class IndicatorLigth : UserControl
{
public IndicatorLigth()
{
InitializeComponent();
DataContext = this;
CurrentBrush = new SolidColorBrush(InactiveColor);
lIndicator.Background = CurrentBrush;
TurnOnValue = true;
Value = true;
}
public static readonly DependencyProperty ActiveColorProperty =
DependencyProperty.Register("ActiveColor", typeof(Color), typeof(IndicatorLigth), new UIPropertyMetadata(Colors.Green));
public Color ActiveColor
{
get { return (Color)GetValue(ActiveColorProperty); }
set { SetValue(ActiveColorProperty, value); }
}
public static readonly DependencyProperty InactiveColorProperty =
DependencyProperty.Register("InactiveColor", typeof(Color), typeof(IndicatorLigth), new UIPropertyMetadata(Colors.Red));
public Color InactiveColor
{
get { return (Color)GetValue(InactiveColorProperty); }
set { SetValue(InactiveColorProperty, value); }
}
private SolidColorBrush _currentBrush;
public SolidColorBrush CurrentBrush
{
get { return _currentBrush; }
set { _currentBrush = value; }
}
public static readonly DependencyProperty TurnOnValueProperty =
DependencyProperty.Register("TurnOnValue", typeof(bool), typeof(IndicatorLigth), new UIPropertyMetadata(true));
public bool TurnOnValue
{
get { return (bool)GetValue(TurnOnValueProperty); }
set { SetValue(TurnOnValueProperty, value); }
}
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register("Value", typeof(bool), typeof(IndicatorLigth),
new FrameworkPropertyMetadata(true,
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnSetColorChanged));
public bool Value
{
get { return (bool)GetValue(ValueProperty); }
set
{
SetValue(ValueProperty, value);
}
}
private void CheckStatus(bool sign)
{
if (sign == TurnOnValue)
CurrentBrush = new SolidColorBrush(ActiveColor);
else CurrentBrush = new SolidColorBrush(InactiveColor);
}
private static void OnSetColorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
IndicatorLigth mycontrol = d as IndicatorLigth;
mycontrol.callmyInstanceMethod(e);
}
private void callmyInstanceMethod(DependencyPropertyChangedEventArgs e)
{
CheckStatus((bool)e.NewValue);
lIndicator.Background = CurrentBrush;
}
}
}
And XAML where I use my usercontrol (I use it in another UserControl):
<UserControl
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:local="clr-namespace:test"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" >
...
<StackPanel Orientation="Vertical">
<Label Content="{Binding RelativeSource={RelativeSource AncestorType=UserControl, Mode=FindAncestor}, Path=DataContext.Sign}"/>
<StackPanel>
<local:IndicatorLigth ActiveColor="Thistle" Value="{Binding RelativeSource={RelativeSource AncestorType=UserControl, Mode=FindAncestor}, Path=DataContext.Sign}"/>
</StackPanel>
</StackPanel>
The Sign parameter belongs to an IsEnabled bindable property of a ComboBox which not in the XAML code. The label content is correct, it changes when I change combobox enabled status, but my UserControl setter of Value, OnSetColorChanged and callmyInstanceMethod don't fire. Could you tell me what wrong in my code? Thank you very much.
Update: So I was wrong. The code mentioned above is correct. The problem will be occures when I push the stackpanel into a devexpress LayoutGroup HeaderTemplate:
<dxlc:LayoutGroup Orientation="Vertical" VerticalAlignment="Top">
<dxlc:LayoutGroup.HeaderTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<Label Content="{Binding RelativeSource={RelativeSource AncestorType=UserControl, Mode=FindAncestor}, Path=DataContext.Sign}"/>
<StackPanel>
<local:IndicatorLigth ActiveColor="Thistle" Value="{Binding RelativeSource={RelativeSource AncestorType=UserControl, Mode=FindAncestor}, Path=DataContext.Sign}"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</dxlc:LayoutGroup.HeaderTemplate>
</dxlc:LayoutGroup>
Sorry for disturbing you and thank you for advices. I have found the cause of problem. I needn't use <HeaderTemplate><DataTemplate>, I have to use simple <Header> block :)

DependencyProperty for collection of buttons

I want to give the user the opportunity to set a collection of buttons in my CustomControl.
I tried to solve this with ItemsControl like this:
<ItemsControl ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type cc:MyCustomControl}}, Path=Buttons}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Command="{Binding Command}">
<Image Source="{Binding MyImageSource}"/>
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Buttons DependencyProperty:
public static readonly DependencyProperty ButtonsProperty = DependencyProperty.Register(
"Buttons", typeof(IList), typeof(TileGrid), new PropertyMetadata(default(IList)));
public IList Buttons
{
get { return (IList) GetValue(ButtonsProperty); }
set { SetValue(ButtonsProperty, value); }
}
MyButton class:
public class MyButton: Button
{
public ImageSource MyImageSource { get; set; }
}
And how I want to see it in CustomControl implementation:
<cc:MyCustomControl>
<cc:MyCustomControl.Buttons>
<cc:MyButton Command="{Binding SignDocumentsCommand}"
MyImageSource="pack://application:,,,/CommonResources;component/Images/Icons/pen.png"/>
<cc:MyButton Command="{Binding DeleteDocumentsCommand}"
MyImageSource="pack://application:,,,/CommonResources;component/Images/Icons/remove.png"/>
</cc:MyCustomControl.Buttons>
</cc:MyCustomControl>
But it's not working. In live visual tree i see only MyButtons inside ItemsControl. Is this a right approach? Or i need to solve it another way?
The type that you are using for the Button items in the ItemsControl should not be derived from Button. You may use something simple like shown below. It is also not necessary to declare the Buttons property as dependency property. A simple ObservableCollection is sufficient.
public class MyButtonItem : DependencyObject
{
public static DependencyProperty CommandProperty = DependencyProperty.Register(
nameof(Command), typeof(ICommand), typeof(MyButtonItem));
public static DependencyProperty ImageSourceProperty = DependencyProperty.Register(
nameof(ImageSource), typeof(ImageSource), typeof(MyButtonItem));
public ICommand Command
{
get { return (ICommand)GetValue(CommandProperty); }
set { SetValue(CommandProperty, value); }
}
public ImageSource ImageSource
{
get { return (ImageSource)GetValue(ImageSourceProperty); }
set { SetValue(ImageSourceProperty, value); }
}
}
public partial class MyCustomControl : UserControl
{
public MyCustomControl()
{
InitializeComponent();
}
public ObservableCollection<MyButtonItem> Buttons { get; }
= new ObservableCollection<MyButtonItem>();
}
The controls XAML would just be what you already have:
<ItemsControl ItemsSource="{Binding Buttons,
RelativeSource={RelativeSource AncestorType=UserControl}}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Command="{Binding Command}">
<Image Source="{Binding ImageSource}"/>
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
You would then add MyButtonItem objects to the Buttons collection:
<cc:MyCustomControl>
<cc:MyCustomControl.Buttons>
<cc:MyButtonItem
Command="{Binding SignDocumentsCommand}"
ImageSource="/CommonResources;component/Images/Icons/pen.png"/>
<cc:MyButtonItem
Command="{Binding DeleteDocumentsCommand}"
ImageSource="/CommonResources;component/Images/Icons/remove.png"/>
</cc:MyCustomControl.Buttons>
</cc:MyCustomControl>

Passing ModelData (context) between UserControls (views) MVVM Prism

I'm woking on a project and I have three ViewModels: ObjectDetailsViewMode has a Context (property linking to a model) of type ObjectBase; PropertyTextViewModel has a Context of type PropertyText and PropertyNumberViewModel has a Context of type PropertyNumber.
Below is the structure of the Models:
public class ObjectBase : ModelBase
{
private string _name;
public string Name
{
get { return _name; }
set { SetProperty(ref _name, value); }
}
public DataCollection<PropertyBase> Properties { get; } = new DataCollection<PropertyBase>();
}
public class PropertyText : PropertyBase
{
private string _default;
public string Default
{
get { return _default; }
set { SetProperty(ref _default, value); }
}
}
public class PropertyNumber : PropertyBase
{
private double _default = 0;
public double Default
{
get { return _default; }
set { SetProperty(ref _default, value); }
}
private double _minValue = 0;
public double MinValue
{
get { return _minValue; }
set { SetProperty(ref _minValue, value); }
}
private double _maxValue = 0;
public double MaxValue
{
get { return _maxValue; }
set { SetProperty(ref _maxValue, value); }
}
}
Regarding the views I have one for each ViewModel. The ObjectDetailsView is a use control that has a TextBox for editing the Object.Name, two buttons to add new PropertyText/PropertyNumber to the Object.Properties and an ItemsControl connected to that Object.Properties.
Each PropertyBase in the ItemsControl (ItemsSource) is resolved into a new view using the DataTemplate marker:
<ItemsControl ItemsSource="{Binding Object.Properties}">
<ItemsControl.Resources>
<DataTemplate DataType="{x:Type models:PropertyText}">
<views:PropertyTextView />
</DataTemplate>
<DataTemplate DataType="{x:Type models:PropertyNumber}">
<views:PropertyNumberView />
</DataTemplate>
</ItemsControl.Resources>
</ItemsControl>
As I'm using PRISM the correct ViewModel is automatically created for me and the view DataContext is then set to the new ViewModel. My problem is I need to pass the new Property from the Object.Properties list to the newly created View's ViewModel and store it in the Context property I have there.
I can't avoid creating a View/ViewModel for each property type because there is some under-the-hood logic on some Property types (not the ones I described here.. but I have other types like Boolean, Reference, Enum...)
So I really need to pass a value to the ViewModel I tried to use
<ItemsControl ItemsSource="{Binding Object.Properties}">
<ItemsControl.Resources>
<DataTemplate DataType="{x:Type models:PropertyText}">
<views:PropertyTextView Context="{Binding}"/>
</DataTemplate>
<DataTemplate DataType="{x:Type models:PropertyNumber}">
<views:PropertyNumberView Context="{Binding}"/>
</DataTemplate>
</ItemsControl.Resources>
</ItemsControl>
Be aware that Context is a custom property I created inside the ViewModel's to store the ModelContext. I even created a DependencyProperty in the View's behind code:
public PropertyBase Context
{
get { return (PropertyBase)GetValue(ContextProperty); }
set { SetValue(ContextProperty, value); }
}
// Using a DependencyProperty as the backing store for MyProperty. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ContextProperty =
DependencyProperty.Register("Context", typeof(PropertyBase), typeof(PropertyTextView), new PropertyMetadata(null));
But it doesn't get linked to the ViewModels set event (I made a break point there and... nothing). I even tried a SetBinding in the PropertyTextView code-behind (constructor):
string propertyInViewModel = "Context";
var bindingViewMode = new Binding(propertyInViewModel) { Mode = BindingMode.TwoWay };
this.SetBinding(ContextProperty, bindingViewMode);
No luck with any of these... I' really stuck.
Something More Simple
If the PropertyTextView has this dependency property.
public string Context
{
get { return (PropertyBase)GetValue(ContextProperty); }
set { SetValue(ContextProperty, value); }
}
// Using a DependencyProperty as the backing store for Context. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ContextProperty =
DependencyProperty.Register("Context", typeof(string), typeof(PropertyTextBuilderView), new PropertyMetadata(null));
I should be able to do:
right?! Why isn't the public property "Context" not being called (I placed a breakpoint there and I get nothing).
Instead of just setting the Context Property of your View to a new Binding you need to assign the Current DataContext like so:
<views:PropertyNumberView Context="{Binding .}"/>
This should assign the Current Views.DataContext Property to your new View.
If you're in an DataTemplate you probably need to specify the RelativeSource:
<views:PropertyNumberView Context="{Binding Path=DataContext, RelativeSource={RelativeSource AncestorType=UserControl}}
<ItemsControl ItemsSource="{Binding Object.Properties}">
<ItemsControl.Resources>
<DataTemplate DataType="{x:Type models:PropertyText}">
<views:PropertyTextView Context="{Binding .}"/>
</DataTemplate>
<ItemsControl.Resources>
</ItemsControl>
As I'm using PRISM the correct ViewModel is automatically created for me
You don't have to use view-first with Prism. The ViewModelLocator is there to help, if you chose to, but view model-first is possible, too.
If I understand you correctly, you have a view model and want to populate a list with child view models. So do just that:
internal class ParentViewModel : BindableBase
{
public ParentViewModel( ParentModel parentModel, IChildViewModelFactory factory )
{
Children = new object[] { factory.CreateTextViewModel(parentModel.TextProperty), factory.CreateNumberViewModel(parentModel.NumberProperty) };
}
public IEnumerable Children { get; }
}
and map the different child view models to child views via DataTemplates.
parentModel.WhateverProperty will have a Name and Value properties as well as setter for the value, probably...

WPF Binding to Custom Property Not Working

I have this control to display a list of usercontrols
<ItemsControl x:Name="LayersList" Margin="10,284,124,0">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<NaturalGroundingPlayer:LayerControl Item="{Binding}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
The LayerControl control contains this code
public partial class LayerControl : UserControl {
public LayerItem Item { get; set; }
public static readonly DependencyProperty ItemProperty =
DependencyProperty.Register(
"Item",
typeof(LayerItem),
typeof(LayerControl),
new PropertyMetadata(null));
public LayerControl() {
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e) {
// This doesn't work because Item remains null
MainWindow.Instance.LayersList.Items.Remove(Item);
}
}
LayerItem contains this
[PropertyChanged.ImplementPropertyChanged]
public class LayerItem {
public LayerType Type { get; set; }
public string FileName { get; set; }
}
public enum LayerType {
Audio,
Video,
Image
}
Problem is: The Binding is setting the Item property to null. If I change the binding to {Binding Type} instead of {Binding} (and adapt the property type accordingly), then it works. But I can't find a way to bind the whole object. What am I doing wrong?
On a side note, I tried setting ItemsControl.ItemsSource to a ObservableCollection<LayerItem> but that didn't seem to work. Adding items directly to ItemsControl.Items is working. Any idea why that is?
You have incorrectly implemented a dependency property. You should use GetValue and SetValue methods instead of creating an auto-property.
public static readonly DependencyProperty ItemProperty =
DependencyProperty.Register(
"Item", typeof(LayerItem), typeof(LayerControl));
public LayerItem Item
{
get { return (LayerItem)GetValue(ItemProperty); }
set { SetValue(ItemProperty, value); }
}
P.S. You shouldn't access controls like this: MainWindow.Instance.LayersList.Items.Remove(Item). You should use MVVM instead. I'm also not convinced this property is required at all. DataContext may be enough.

Binding to DependencyProperty works only with "MyValue" and not "{Binding PropertyHoldingMyValue}"

I am creating a custom "PageHeaderControl" UserControl, with a header property:
public partial class PageHeaderControl: UserControl
{
public static readonly DependencyProperty HeaderProperty =
DependencyProperty.Register("Header",
typeof(string), typeof(PageHeaderControl),
new PropertyMetadata(""));
public string Header
{
get { return GetValue(HeaderProperty) as string; }
set { SetValue(HeaderProperty, value); }
}
}
In the XAML for that control, I have:
<sdk:Label Content="{Binding Header,Mode=TwoWay}" />
Now for the problem: When I create the control, binding it only works to do this:
<my:PageHeaderControl Header="This is my page header" />
And it does not work to do this, where PageHeader is the property in my ViewModel holding the header value:
<my:PageHeaderControl Header="{Binding PageHeader,Mode=TwoWay}" />
I thought maybe my properties were messed up, but this also works:
<TextBlock Text="{Binding PageHeader,Mode=TwoWay}" />
Any ideas as to what the problem could be!
Thanks so much!!!
Edit:
In my ViewModel, PageHeader is this:
private string _pageHeader = "This is my page header";
public string PageHeader
{
get
{
return _pageHeader;
}
set
{
_pageHeader = value;
RaisePropertyChanged("PageHeader");
}
}
Edit 2:
When I put a breakpoint inside the "get" for my PageHeader property, it does not get hit AT ALL, unless I add in the TextBlock...
If I understand you correctly you're trying to bind a property of an element within your control's XAML markup to the property of the control itself.
If this is the case, see if the following helps you.
PageHeaderControl.xaml:
<UserControl x:Class="TryElementBinding.PageHeaderControl"
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"
x:Name = "MyControl"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<Grid x:Name="LayoutRoot" Background="White">
<TextBlock Text="{Binding Header, ElementName=MyControl}"></TextBlock>
</Grid>
PageHeaderControl.xaml.cs:
public partial class PageHeaderControl : UserControl
{
public static readonly DependencyProperty HeaderProperty =
DependencyProperty.Register("Header", typeof(string), typeof(PageHeaderControl), new PropertyMetadata(""));
public string Header
{
get
{
return GetValue(HeaderProperty) as string;
}
set
{
SetValue(HeaderProperty, value);
}
}
public PageHeaderControl()
{
InitializeComponent();
}
}
ViewModel.cs:
public class ViewModel : INotifyPropertyChanged
{
private string _pageHeader = "This is my page header";
public string PageHeader
{
get
{
return _pageHeader;
}
set
{
_pageHeader = value;
PropertyChanged(this, new PropertyChangedEventArgs("PageHeader"));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
MainPage.xaml:
<Grid x:Name="LayoutRoot" Background="White">
<my:PageHeaderControl Header="{Binding PageHeader, Mode=TwoWay}"></my:PageHeaderControl>
</Grid>
MainPage.xaml.cs:
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
DataContext = new ViewModel();
}
}
I'm a little bit confused and I think you missed the syntax of Binding inline expression.
after "{Binding" comes Path to your property. Is "PageHeader" is a path to your property?!
I think you mean this:
<my:PageHeader Header="{Binding PageHeader, Mode=TwoWay}" />
<TextBlock Text="{Binding PageHeader, Mode=TwoWay}" />
The problem is that Binding expression only works when you set the value of property using SetValue method and notify the parent DependencyObject that specific property has changed!
You should use a DependencyProperty to have TwoWay Binding on it, OR implement System.ComponentModel.INotifyPropertyChange interface in your class and notify the Binding object manually by calling PropertyChanged event in the interface.
The definition of PageHeader property should be like this:
public static readonly DependencyProperty PageHeaderProperty = DependencyProperty.Register("PageHeader", typeof(string), typeof(YOUROWNER), new PropertyMetadata(""));
public string PageHeader
{
get { return GetValue(PageHeaderProperty) as string; }
set { SetValue(PageHeaderProperty, value); }
}
Cheers

Categories