Reputation: 4427
I'm making a custom date and time usercontrol, but running into a problem getting the binding to work. I think everything is working on the usercontrol side?. But not on the window side. My little test setup should update the window's title with the date and time selected on the control when you click a button. Currently it's not updating the new date. If I set a breakpoint on myDate
's setter it doesn't get called when I change the date. How do I correctly bind to a usercontrol?
Usercontrol xaml
<UserControl x:Class="DateTimeCntrl.DateTimeControl"
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:DateTimeCntrl"
mc:Ignorable="d"
d:DesignHeight="32" d:DesignWidth="800">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<ComboBox Grid.Column="0"
x:Name="cbMonth"
SelectionChanged="cb_SelectionChanged"
DisplayMemberPath="Key"
SelectedValuePath="Value"/>
<ComboBox Grid.Column="1"
x:Name="cbDay"
SelectionChanged="cb_SelectionChanged"
DisplayMemberPath="Key"
SelectedValuePath="Value"/>
<ComboBox Grid.Column="2"
x:Name="cbYear"
SelectionChanged="cb_SelectionChanged"
DisplayMemberPath="Key"
SelectedValuePath="Value"/>
<ComboBox Grid.Column="3"
x:Name="cbHour"
SelectionChanged="cb_SelectionChanged"
DisplayMemberPath="Key"
SelectedValuePath="Value"/>
<ComboBox Grid.Column="4"
x:Name="cbMinute"
SelectionChanged="cb_SelectionChanged"
DisplayMemberPath="Key"
SelectedValuePath="Value"/>
<ComboBox Grid.Column="5"
x:Name="cbAmPm"
SelectionChanged="cb_SelectionChanged"
DisplayMemberPath="Key"
SelectedValuePath="Value"/>
</Grid>
</UserControl>
Usercontrol code behind
public partial class DateTimeControl : UserControl {
public static readonly DependencyProperty SetDateProperty = DependencyProperty.Register("Date", typeof(DateTime), typeof(DateTimeControl), new PropertyMetadata(DateTime.Now, new PropertyChangedCallback(OnDateChanged)));
public DateTime Date {
get { return (DateTime)GetValue(SetDateProperty); }
set { SetValue(SetDateProperty, value); }
}
public int Month { get { return cbMonth.SelectedValue == null ? 1 : (int)cbMonth.SelectedValue; } }
public int Day { get { return cbDay.SelectedValue == null ? 1 : (int)cbDay.SelectedValue; } }
public int Year { get { return cbYear.SelectedValue == null ? 1999 : (int)cbYear.SelectedValue; } }
public int Hour { get { return cbHour.SelectedValue == null ? 1 : (int)cbHour.SelectedValue; } }
public int Minute { get { return cbMinute.SelectedValue == null ? 1 : (int)cbMinute.SelectedValue; } }
public int AmPm { get { return cbAmPm.SelectedValue == null ? 1 : (int)cbAmPm.SelectedValue; } }
private static void OnDateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
}
private void OnDateChanged(DependencyPropertyChangedEventArgs e) {
DateTime now = (DateTime)e.NewValue;
cbMonth.SelectedValue = now.Month;
cbDay.SelectedValue = now.Day;
cbYear.SelectedValue = now.Year;
cbHour.SelectedValue = now.Hour > 12 ? now.Hour - 12 : now.Hour;
cbMinute.SelectedValue = now.Minute;
cbAmPm.SelectedValue = now.Hour > 12 ? 2 : 1;
}
public DateTimeControl() {
InitializeComponent();
//DataContext = this;
DateTime now = DateTime.Now;
//Months
for(int i = 1; i < 13; i++) {
string m = CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(i);
cbMonth.Items.Add(new KeyValuePair<string, int>(m, i));
}
cbMonth.SelectedValue = now.Month;
//Days
for(int i = 1; i < 32; i++) {
string d;
if (i < 10)
d = "0" + i.ToString();
else
d = i.ToString();
cbDay.Items.Add(new KeyValuePair<string, int>(d, i));
}
cbDay.SelectedValue = now.Day;
//Years
for(int i = DateTime.Now.Year; i > DateTime.Now.Year - 10; i--) {
cbYear.Items.Add(new KeyValuePair<string, int>(i.ToString(), i));
}
cbYear.SelectedValue = now.Year;
//Hours
for(int i = 1; i < 13; i++) {
cbHour.Items.Add(new KeyValuePair<string, int>(i.ToString(), i));
}
cbHour.SelectedValue = now.Hour > 12 ? now.Hour - 12 : now.Hour;
//Minutes
for (int i = 0; i < 60; i++) {
string m;
if (i < 10)
m = "0" + i.ToString();
else
m = i.ToString();
cbMinute.Items.Add(new KeyValuePair<string, int>(m, i));
}
cbMinute.SelectedValue = now.Minute;
//AM PM
cbAmPm.Items.Add(new KeyValuePair<string, int>("Am", 1));
cbAmPm.Items.Add(new KeyValuePair<string, int>("Pm", 2));
cbAmPm.SelectedValue = now.Hour > 12 ? 2 : 1;
}
private void updateTime() {
Date = new DateTime(Year, Month, Day, Hour + AmPm == 2 ? 12 : 0, Minute, 0);
}
private void cb_SelectionChanged(object sender, SelectionChangedEventArgs e) {
updateTime();
}
}
Main Window xaml
<Window x:Class="DateTimeCntrl.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:DateTimeCntrl"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<local:DateTimeControl Date="{Binding myDate}"/>
<Button Grid.Row="1" Click="Button_Click">click me</Button>
</Grid>
</Window>
Main Window xaml
public partial class MainWindow : Window {
MainViewModel viewmodel;
public MainWindow() {
InitializeComponent();
DataContext = viewmodel = new MainViewModel();
}
private void Button_Click(object sender, RoutedEventArgs e) {
Title = viewmodel.myDate.ToString();
}
}
Main Window View Model
public class MainViewModel : BaseViewModel {
private DateTime mydate;
public DateTime myDate {
get {
return mydate;
}
set {
mydate = value;
RaisePropertyChanged("myDate");
}
}
}
Upvotes: 1
Views: 1319
Reputation: 10839
Use the TwoWay binding mode Date="{Binding myDate, Mode=TwoWay}"
in Window xaml
while binding to dependency property.
<local:DateTimeControl Date="{Binding myDate, Mode=TwoWay}"/>
Upvotes: 1