2017-02-22 48 views
1

У меня проблема с моим WPF UserControl, связывающим одно свойство с несколькими элементами управления и обратно. Установщики бизнес-объекта не будут вызваны. Я искал часы и пробовал серверные вещи, которые не сработали.WPF UserControl: setter не вызвал привязку одного свойства в нескольких элементах управления и обратно

Мой код

можно скачать здесь: WpfApplicationUserControlProblem.zip

Мой бизнес объект 2 DateTime Значения должны быть связаны.

public class BusinessObject 
{ 
    private DateTime _value1 = DateTime.Today.AddHours(10); 
    public DateTime Value1 
    { 
     get { return _value1; } 
     set { _value1 = value; }  // will never be called but why?? 
    } 

    private DateTime _value2 = DateTime.Today.AddDays(1).AddHours(15); 
    public DateTime Value2 
    { 
     get { return _value2; } 
     set { _value2 = value; }  // will never be called but why?? 
    } 
} 

Мой Main-Window имеет 2 пользовательские элементы управление, чтобы связать 2 значения моего объекта

<Window x:Class="WpfApplicationUserControlProblem.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:WpfApplicationUserControlProblem" 
    mc:Ignorable="d" 
    Title="MainWindow" Height="120.961" Width="274.489"> 
<Grid> 
    <local:DateTimeUserControl DateTimeValue="{Binding Value1, UpdateSourceTrigger=PropertyChanged}" Margin="10,10,0,0" VerticalAlignment="Top" HorizontalAlignment="Left" Width="241"/> 
    <local:DateTimeUserControl DateTimeValue="{Binding Value2, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Left" Margin="10,39,0,0" VerticalAlignment="Top" Width="241"/> 
</Grid> 

public partial class MainWindow : Window 
{ 
    private BusinessObject _businessObject = new BusinessObject(); 
    public MainWindow() 
    { 
     InitializeComponent(); 
     DataContext = _businessObject; 
    } 
} 

Моего UserControl DateTimeUserControl имеет один DependencyProperty "DateTimeValue" для получения связанного бизнес-ценность из главного окна. С помощью «DateTimeValuePropertyChangedCallback» я перенаправляю полученное значение в DateValue для DatePicker и HourValue для HourTextBox. Изменение DatePicker или HourTextBox должно обновлять DependencyProperty «DateTimeValue» и, следовательно, также ограниченный бизнес-объект. Это был мой план.

<UserControl x:Class="WpfApplicationUserControlProblem.DateTimeUserControl" 
     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:WpfApplicationUserControlProblem" 
     x:Name="_this" 
     mc:Ignorable="d"> 
<Grid> 
    <DatePicker SelectedDate="{Binding Path=DateValue, ElementName=_this, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top" Margin="0,0,61,0"/> 
    <TextBox Text="{Binding Path=HourValue, ElementName=_this, UpdateSourceTrigger=PropertyChanged}" Height="24" VerticalAlignment="Top" HorizontalAlignment="Right" Width="56"/> 
</Grid> 

public partial class DateTimeUserControl : UserControl, INotifyPropertyChanged 
{ 
    public DateTimeUserControl() 
    { 
     InitializeComponent(); 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    public static readonly DependencyProperty DateTimeValueProperty = DependencyProperty.Register(nameof(DateTimeValue), typeof(DateTime), typeof(DateTimeUserControl), new PropertyMetadata(DateTimeValuePropertyChangedCallback)); 
    public DateTime DateTimeValue 
    { 
     get { return (DateTime)GetValue(DateTimeValueProperty); } 
     set { SetValue(DateTimeValueProperty, value); } 
    } 

    private static void DateTimeValuePropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     DateTimeUserControl control = d as DateTimeUserControl; 
     control.FirePropertyChanged(d, new PropertyChangedEventArgs(nameof(DateValue))); 
     control.FirePropertyChanged(d, new PropertyChangedEventArgs(nameof(HourValue))); 
    } 

    private void FirePropertyChanged(object sender, PropertyChangedEventArgs args) 
    { 
     PropertyChanged?.Invoke(sender, args); 
    } 

    public DateTime DateValue 
    { 
     get { return DateTimeValue.Date; } 
     set { DateTimeValue = value.Date.AddHours(DateTimeValue.Hour); } 
    } 

    public string HourValue 
    { 
     get { return DateTimeValue.Hour.ToString(); } 
     set { DateTimeValue = DateTimeValue.Date.AddHours(int.Parse(value)); } 
    } 
} 

Я не понимаю

Все, кажется, работает хорошо, за исключением, что законодательницей бизнес-объекта не вызывается, когда DependencyProperty обновляется. Но почему? Я также пробовал все с DependencyProperties или MultiBindingConverters. Я потерпел неудачу при каждой попытке.

Может ли кто-нибудь помочь?

ответ

1

The DateTimeValue креплений должно быть объявлен как TwoWay, в то время как UpdateSourceTrigger=PropertyChanged конечно лишняя:

<local:DateTimeUserControl DateTimeValue="{Binding Value1, Mode=TwoWay}" .../> 

Вы также можете объявить свойство DateTimeValue зависимостей для привязки двухстороннего по умолчанию:

public static readonly DependencyProperty DateTimeValueProperty = 
    DependencyProperty.Register(
     nameof(DateTimeValue), 
     typeof(DateTime), 
     typeof(DateTimeUserControl), 
     new FrameworkPropertyMetadata(
      default(DateTime), 
      FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, 
      DateTimeValuePropertyChangedCallback)); 

Вы можете спросить, почему это также не необходимо для двух «внутренних» привязок в XAM UserControl L, но и DatePicker.SelectedDate, и имущество TextBox.Text уже зарегистрированы в BindsTwoWayByDefault.

+0

Спасибо! Ты мой герой дня! Режим = TwoWay - это трюк. – jaz