I'm trying to create a Datagrid with Paging, but I haven't gotten that far.
Right now I have this.
<UserControl x:Class="SampleControls.UserControls.PageFilterGrid"
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:local="clr-namespace:SampleControls.UserControls"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="500"
Name="Ultra">
<Grid>
<DataGrid Name="MyGrid" AutoGenerateColumns="{Binding ElementName=Ultra, Path=AutoGenerateColumns}" ItemsSource="{Binding ElementName=Ultra, Path=MyItemsSource}" />
</Grid>
The Codebehind for that control looks like this:
public partial class PageFilterGrid : UserControl
{
public PageFilterGrid()
{
InitializeComponent();
}
public static readonly DependencyProperty MyItemsSourceProperty = DependencyProperty.Register("MyItemsSource",
typeof(IEnumerable), typeof(PageFilterGrid));
public static readonly DependencyProperty GenerateColumns = DependencyProperty.Register("AutoGenerateColumns",
typeof(bool), typeof(PageFilterGrid), new PropertyMetadata(false));
public static readonly DependencyProperty MyUltraGrid = DependencyProperty.Register("UltraGrid",
typeof(DataGrid), typeof(PageFilterGrid), new PropertyMetadata(new DataGrid()));
public IEnumerable MyItemsSource
{
get
{
return (IEnumerable)GetValue(PageFilterGrid.MyItemsSourceProperty);
}
set
{
SetValue(PageFilterGrid.MyItemsSourceProperty, value);
}
}
public bool AutoGenerateColumns
{
get
{
return (bool)GetValue(PageFilterGrid.GenerateColumns);
}
set
{
SetValue(PageFilterGrid.GenerateColumns, value);
}
}
public DataGrid UltraGrid {
get
{
return (DataGrid)GetValue(PageFilterGrid.MyUltraGrid);
}
set
{
SetValue(PageFilterGrid.MyUltraGrid, value);
}
}
}
My question is, if I dont want to autogenerate columns , how can i specify the columns without adding them in code behind? I want to add them to the grid like you would normally in XAML. Something like this below, but this doesn't work.
I've tried bringing back just the columns and setting that property, but that doesn't seem to work either for the XAML.
<controls:PageFilterGrid x:Name="myultra" AutoGenerateColumns="False" MyItemsSource="{Binding MyCollection}">
<controls:PageFilterGrid.UltraGrid>
<controls:PageFilterGrid.UltraGrid.Columns>
<DataGridTextColumn Header="amount" Binding="{Binding}" />
</controls:PageFilterGrid.UltraGrid.Columns>
</controls:PageFilterGrid.UltraGrid>
</controls:PageFilterGrid>
Related
I am working on a reusable content dialog UserControl that the user can import into their xaml and only have to be responsible for bindings in their respective ViewModel. My UserControl has DependencyProperties tied to appropriate content, but the Content Dialog event's are not visible (programmatically) to users of the UserControl. Specifically, I am looking for .ShowAsync()., but Intellisense does not see .ShowAsync() as being part of UserControl.
I used the examples here as a pattern, but I don't need to extend the DialogContent class for my purpose (I think?): https://learn.microsoft.com/en-us/uwp/api/Windows.UI.Xaml.Controls.ContentDialog
As an experiment, I tried to make this SO work, but I then realized this was sitting on Template 10 framework and Dependency Injection/IoC (I am doing my app in straight C#): UWP ContentDialog Invocation
Here is my UserControl's code behind:
public partial class UserDefinedDialogView : UserControl
{
public static readonly DependencyProperty TitleProperty =
DependencyProperty.Register("DialogTitle", typeof(string), typeof(UserDefinedDialogView), null);
public static readonly DependencyProperty DialogContentTextProperty =
DependencyProperty.Register("DialogContent", typeof(string), typeof(UserDefinedDialogView), null);
public static readonly DependencyProperty PrimaryButtonTextProperty =
DependencyProperty.Register("DialogPrimaryButtonText", typeof(string), typeof(UserDefinedDialogView), null);
public static readonly DependencyProperty SecondaryButtonTextProperty =
DependencyProperty.Register("DialogSecondaryButtonText", typeof(string), typeof(UserDefinedDialogView), null);
public static readonly DependencyProperty CloseButtonTextProperty =
DependencyProperty.Register("DialogCloseButtonText", typeof(string), typeof(UserDefinedDialogView), null);
// PropertyWrappers
public string DialogTitle
{
get { return (string)GetValue(TitleProperty); }
set { SetValue(TitleProperty, value); }
}
public string DialogContent
{
get { return (string)GetValue(DialogContentTextProperty); }
set { SetValue(DialogContentTextProperty, value); }
}
public string DialogPrimaryButtonText
{
get { return (string)GetValue(PrimaryButtonTextProperty); }
set { SetValue(PrimaryButtonTextProperty, value); }
}
public string DialogSecondaryButtonText
{
get { return (string)GetValue(SecondaryButtonTextProperty); }
set { SetValue(SecondaryButtonTextProperty, value); }
}
public string DialogCloseButtonText
{
get { return (string)GetValue(CloseButtonTextProperty); }
set { SetValue(CloseButtonTextProperty, value); }
}
public UserDefinedDialogView()
{
this.InitializeComponent();
}
}
The UserControl's xaml:
<UserControl
x:Class="HHPM_NEXT.Views.Common.UserDefinedDialogView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:HHPM_NEXT.Views.Common"
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">
<ContentDialog x:Name="UserDefinedDialog"
Title="{x:Bind DialogTitle, Mode=TwoWay}"
Content="{x:Bind DialogContent, Mode=TwoWay}"
PrimaryButtonText="{x:Bind DialogPrimaryButtonText, Mode=TwoWay}"
CloseButtonText="{x:Bind DialogCloseButtonText, Mode=TwoWay}"
x:FieldModifier="Public">
</ContentDialog>
</UserControl>
Example Implementation (References to Zeroize are in a ViewModel, but I didn't add it because I didn't want this to get too long):
<views1:UserDefinedDialogView x:Name="ConfimationDialog" DialogTitle="{Binding ZeroizeTitle, Mode=TwoWay}" DialogContent="{Binding ZeroizeContent, Mode=TwoWay}"
DialogPrimaryButtonText="{Binding ZeroizeConfirmButtonText, Mode=TwoWay}" DialogCloseButtonText="{Binding ZeroizeCloseButtonText, Mode=TwoWay}"/>
I have a problem with binding in usercontrol.
This is my usercontrol:
UserControl1.xaml
<UserControl x:Class="WpfApp1.UserControl1"
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-ompatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
x:Name="usercontrol"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<TextBox Text="{Binding HmiField, ElementName=usercontrol}"/>
</Grid>
</UserControl>
UserControl1.xaml.cs
namespace WpfApp1
{
public partial class UserControl1 : UserControl
{
public double HmiField
{
get { return (double)GetValue(HmiFieldProperty); }
set { SetValue(HmiFieldProperty, value); }
}
public static readonly DependencyProperty HmiFieldProperty =
DependencyProperty.Register("HmiField", typeof(double), typeof(UserControl1));
public UserControl1()
{
InitializeComponent();
}
}
}
And this is the main window:
MainWindow.xaml
<Window x:Class="WpfApp1.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:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
DataContext="{Binding Md, RelativeSource={RelativeSource Self}}"
Title="MainWindow" Height="450" Width="800">
<UniformGrid>
<Button Content="{Binding Prop1}" Click="Button_Click"/>
<Label Content="{Binding Prop1}"/>
<TextBox Text="{Binding Prop1}"/>
<local:UserControl1 HmiField="{Binding Prop1}"/>
</UniformGrid>
</Window>
MainWindow.xaml.cs
namespace WpfApp1
{
public class tMd: INotifyPropertyChanged
{
#region Interfaccia INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
}
#endregion
private double prop1;
public double Prop1 { get
{
return prop1;
}
set
{
if (prop1 != value)
{
prop1 = value;
NotifyPropertyChanged("Prop1");
}
}
}
}
public partial class MainWindow : Window
{
public tMd Md
{
get { return (tMd)GetValue(MdProperty); }
set { SetValue(MdProperty, value); }
}
public static readonly DependencyProperty MdProperty =
DependencyProperty.Register("Md", typeof(tMd), typeof(MainWindow), new PropertyMetadata(new tMd()));
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Md.Prop1 = 1234.5678;
}
}
}
I found some similar question:
How do I change TextBox.Text without losing the binding in WPF?
WPF: Binding is lost when bindings are updated
WPF Textbox TwoWay binding in datatemplate not updating the source even on LostFocus
But I can't completely understand what's happening: why a standard textbox work as expected and my usercontrol no?
Or better: is there a way to have my usercontrol works with the textbox's behaviour?
The Binding must be TwoWay, either set explicitly
<local:UserControl1 HmiField="{Binding Prop1, Mode=TwoWay}"/>
or implicitly by default:
public static readonly DependencyProperty HmiFieldProperty =
DependencyProperty.Register(
nameof(HmiField), typeof(double), typeof(UserControl1),
new FrameworkPropertyMetadata(
0d, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
A TextBox's Text property is registered like shown above, i.e. with the BindsTwoWayByDefault flag.
At the TextBox Binding in the UserControl's XAML you may also want to update the source property while the user is typing (instead of only on lost focus):
<TextBox Text="{Binding HmiField,
ElementName=usercontrol,
UpdateSourceTrigger=PropertyChanged}"/>
or without the otherwise useless generated usercontrol field:
<TextBox Text="{Binding HmiField,
RelativeSource={RelativeSource AncestorType=UserControl}
UpdateSourceTrigger=PropertyChanged}"/>
Your Prop1 notifies when it changes, but you haven't told you binding to trigger on that notification.
Try including UpdateSourceTrigger=PropertyChanged in you binding
In a WPF project (code below) I have a UserControl of type MyUserControl with a dependency property, called MyOrientation of type Orientation.
On the MainWindow I have 2 instances of MyUserControl, where via XAML I set the Orientation property on one to be Horizontal and the other instance to be Vertical.
I have made the MyOrientation property a DP as I want the ability to set it directly in XAML as in this example or using a binding.
My problem is that when I run the project both instances of the UserControl show up with the Orientation = Horizontal?
Could someone please tell me what I am doing wrong and how to fix it?
Many thanks in advance.
Here is the code:
MYUSERCONTROLVIEWMODEL:
public class MyUserControlViewModel : ViewModelBase
{
private Orientation _myOrientation;
public Orientation MyOrientation
{
get { return _myOrientation; }
set
{
if (_myOrientation == value)
return;
_myOrientation = value;
OnPropertyChanged();
}
}
}
MYUSERCONTROL.XAML
<UserControl x:Class="TestUserControlDPProblem.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"
xmlns:local="clr-namespace:TestUserControlDPProblem"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid x:Name="root">
<Grid.DataContext>
<local:MyUserControlViewModel/>
</Grid.DataContext>
<StackPanel Orientation="{Binding MyOrientation}">
<TextBlock>Hello</TextBlock>
<TextBlock>There</TextBlock>
</StackPanel>
</Grid>
MYUSERCONTROL CODE BEHIND:
public partial class MyUserControl : UserControl
{
MyUserControlViewModel _vm;
public MyUserControl()
{
InitializeComponent();
_vm = root.DataContext as MyUserControlViewModel;
}
public static readonly DependencyProperty MyOrientationProperty = DependencyProperty.Register("MyOrientation", typeof(Orientation), typeof(MyUserControl), new FrameworkPropertyMetadata(Orientation.Vertical, new PropertyChangedCallback(OnMyOrientationChanged)));
private static void OnMyOrientationChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
var myUserControl = o as MyUserControl;
myUserControl?.OnMyOrientationChanged((Orientation)e.OldValue, (Orientation)e.NewValue);
}
protected virtual void OnMyOrientationChanged(Orientation oldValue, Orientation newValue)
{
_vm.MyOrientation = newValue;
}
public Orientation MyOrientation
{
get
{
return (Orientation)GetValue(MyOrientationProperty);
}
set
{
SetValue(MyOrientationProperty, value);
}
}
}
MAINWINDOW.XAML
<Window x:Class="TestUserControlDPProblem.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:local="clr-namespace:TestUserControlDPProblem"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<StackPanel>
<local:MyUserControl Margin="10" MyOrientation="Horizontal"/>
<local:MyUserControl Margin="10" MyOrientation="Vertical"/>
</StackPanel>
</Grid>
The "internal" view model of the UserControl makes no sense and should not be there. You should instead bind directly to the dependency property by means of a RelativeSource or ElementName Binding:
<StackPanel Orientation="{Binding MyOrientation,
RelativeSource={RelativeSource AncestorType=UserControl}}">
You wouldn't even need the PropertyChangedCallback:
public partial class MyUserControl : UserControl
{
public MyUserControl()
{
InitializeComponent();
}
public static readonly DependencyProperty MyOrientationProperty =
DependencyProperty.Register(
nameof(MyOrientation), typeof(Orientation), typeof(MyUserControl),
new FrameworkPropertyMetadata(Orientation.Vertical));
public Orientation MyOrientation
{
get { return (Orientation)GetValue(MyOrientationProperty); }
set { SetValue(MyOrientationProperty, value); }
}
}
I am trying to define a user control for the typical dual list situation (where there are two lists of items side by side and button controls to cause selected items from one to be transferred to the other). I am not very proficient at WPF -- most of what I've learned has been bits and pieces through sites like this. I have learned that I can create custom dependency properties for the control so that I can defer binding of items in the control (buttons, textboxes, etc.) until the control is actually used which is great. However, for my control I am going to have the two lists (probably DataGrids since most of my code, to date, has involved them) but they will require a lot more than binding so what I would like to do is something like this:
<MyUserControl . . . .>
<DataGrid . . . .>
<DataGrid . . . .>
</MyUserControl>
But I have no idea how to make that work. I thought there might be some way I could use ContentControls as a stand-in for the DataGrids and then somehow link the datagrids back to the contentcontrols in the usercontrol but I don't really understand Contentcontrols and none of the examples I found using them seemed to apply at all to what I want to do.
Can anyone point me in the right direction on this? Thank you.
I did some more research and found a promising approach, here:
How to add controls dynamically to a UserControl through user's XAML?
I did a small proof-of-concept project and it worked great so I thought I would share it here. It uses Galasoft's MVVM Light framework.
I created a user control with a textblock, a ContentControl, and a button:
<UserControl x:Class="DataGridInUserControlDemo.UserControls.DGPlusUC"
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"
x:Name="ControlRoot">
<Grid DataContext="{Binding ElementName=ControlRoot}" Margin="10, 10, 10, 10" MinHeight="300" MinWidth="300">
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="5*"/>
<RowDefinition Height="2*"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="{Binding Path=BannerText}" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="20"/>
<ContentControl Grid.Row="1" Content="{Binding Path=InnerContent}" />
<Button Grid.Row="2" x:Name="DemoButton" Content="{Binding Path=ButtonContent}" Command="{Binding Path=ButtonCommand}" Width="75" Height="25" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
</UserControl>
The attributes I wish to bind external to the UserControl are themselves bound to custom DependencyProperty(s).
This is the code-behind for the user control containing the DependencyProperty definitions:
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace DataGridInUserControlDemo.UserControls
{
public partial class DGPlusUC : UserControl
{
public DGPlusUC()
{
InitializeComponent();
}
public const string BannerTextPropertyName = "BannerText";
public string BannerText
{
get
{
return (string)GetValue(BannerTextProperty);
}
set
{
SetValue(BannerTextProperty, value);
}
}
public static readonly DependencyProperty BannerTextProperty = DependencyProperty.Register(
BannerTextPropertyName,
typeof(string),
typeof(DGPlusUC));
public const string ButtonContentPropertyName = "ButtonContent";
public string ButtonContent
{
get
{
return (string)GetValue(ButtonContentProperty);
}
set
{
SetValue(ButtonContentProperty, value);
}
}
public static readonly DependencyProperty ButtonContentProperty = DependencyProperty.Register(
ButtonContentPropertyName,
typeof(string),
typeof(DGPlusUC));
public const string ButtonCommandPropertyName = "ButtonCommand";
public ICommand ButtonCommand
{
get
{
return (ICommand)GetValue(ButtonCommandProperty);
}
set
{
SetValue(ButtonCommandProperty, value);
}
}
public static readonly DependencyProperty ButtonCommandProperty = DependencyProperty.Register(
ButtonCommandPropertyName,
typeof(ICommand),
typeof(DGPlusUC));
public const string InnerContentPropertyName = "InnerContent";
public UIElement InnerContent
{
get
{
return (UIElement)GetValue(InnerContentProperty);
}
set
{
SetValue(InnerContentProperty, value);
}
}
public static readonly DependencyProperty InnerContentProperty = DependencyProperty.Register(
InnerContentPropertyName,
typeof(UIElement),
typeof(DGPlusUC));
}
}
This is the XAML for the main window:
<Window x:Class="DataGridInUserControlDemo.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"
xmlns:demo="clr-namespace:DataGridInUserControlDemo.UserControls"
mc:Ignorable="d ignore"
Height="400"
Width="400"
Title="MVVM Light Application"
DataContext="{Binding Main, Source={StaticResource Locator}}">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Skins/MainSkin.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid x:Name="LayoutRoot">
<demo:DGPlusUC BannerText="{Binding UCTitle}" ButtonContent="{Binding ButtonText}" ButtonCommand="{Binding ButtonCommand}" HorizontalAlignment="Center" VerticalAlignment="Center">
<demo:DGPlusUC.InnerContent>
<Grid DataContext="{Binding Main, Source={StaticResource Locator}}">
<DataGrid ItemsSource="{Binding Path=DataItems}" AutoGenerateColumns="True" />
</Grid>
</demo:DGPlusUC.InnerContent>
</demo:DGPlusUC>
</Grid>
</Window>
The custom DependencyProperty(s) are used as tags in the control to bind to the properties in the ViewModel.
Note the bracketed demo:DGPlusUC.InnerContent -- this is where the replacement code for the ContentControl goes. The embedded UserControl inherits the Window's datacontext but for some reason this section did not, so, after experimenting with it a bit, I just threw up my hands and declared the DataContext explicitly.
And here is the ViewModel code:
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.CommandWpf;
using DataGridInUserControlDemo.Model;
using System.Windows.Input;
using System.Collections.ObjectModel;
namespace DataGridInUserControlDemo.ViewModel
{
public class MainViewModel : ViewModelBase
{
private readonly IDataModel theModel;
private ObservableCollection<DataItem> _DataItems;
public ObservableCollection<DataItem> DataItems
{
get
{
return _DataItems;
}
set
{
if (_DataItems == value)
{
return;
}
var oldValue = _DataItems;
_DataItems = value;
RaisePropertyChanged(() => DataItems, oldValue, value, true);
}
}
private string _ButtonText = "First";
public string ButtonText
{
get
{
return this._ButtonText;
}
set
{
if (this._ButtonText == value)
{
return;
}
var oldValue = this._ButtonText;
this._ButtonText = value;
RaisePropertyChanged(() => ButtonText, oldValue, value, true);
}
}
private string _UCTitle = string.Empty;
public string UCTitle
{
get
{
return this._UCTitle;
}
set
{
if (this._UCTitle == value)
{
return;
}
var oldValue = this._UCTitle;
this._UCTitle = value;
RaisePropertyChanged(() => UCTitle, oldValue, value, true);
}
}
private ICommand _ButtonCommand;
public ICommand ButtonCommand
{
get
{
return this._ButtonCommand;
}
set
{
if (this._ButtonCommand == value)
{
return;
}
var oldValue = this._ButtonCommand;
this._ButtonCommand = value;
RaisePropertyChanged(() => ButtonCommand, oldValue, value, true);
}
}
public MainViewModel(IDataModel model)
{
this.theModel = model;
this._UCTitle = "DataGrid in User Control Demo";
this._DataItems = new ObservableCollection<DataItem>(this.theModel.SomeData);
this._ButtonCommand = new RelayCommand(this.ButtonCmd, () => { return true; }) ;
}
private void ButtonCmd()
{
if (this.ButtonText == "First")
{
this.ButtonText = "Second";
}
else
{
this.ButtonText = "First";
}
}
}
}
Finally, here are the results:
DataGrid in UserControl Demo
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