Сбой привязки данных в простом UserControl - PullRequest
1 голос
/ 10 января 2012

Во-первых, извинения за весь XAML.Я пытался решить эту проблему несколько дней, но, должно быть, мне чего-то не хватает.Вкратце вопрос заключается в том, что мое свойство зависимости UserControl не отображается для привязки данных в коде при его использовании.

Подробности: у меня есть следующий простой UserControl (в своей собственной dll), где я использую ползунок с 0..59 для выбора секунд, а UserControl имеет свойство зависимости Valueкоторый возвращает TimeSpan, состоящий из секунд, выбранных с помощью ползунка:

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

    private int _seconds;

    public event PropertyChangedEventHandler PropertyChanged;

    private void RaisePropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
    public int Seconds
    {
        get { return _seconds; }
        set
        {
            if (_seconds == value)
                return;
            _seconds = value;
            RaisePropertyChanged("Seconds");

            var t = Value;
            Value = new TimeSpan(t.Hours, t.Minutes, _seconds);
        }
    }

    public TimeSpan Value
    {
        get { return (TimeSpan) GetValue(ValueProperty); }
        set { SetValue(ValueProperty, value); }
    }

    private static void OnValueChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
        TinyTimeSpanControl control = obj as TinyTimeSpanControl;
        var newValue = (TimeSpan)e.NewValue;

        control.Seconds = newValue.Seconds;
    }

    public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
      "Value", typeof(TimeSpan), typeof(TinyTimeSpanControl), new PropertyMetadata(OnValueChanged));
}

С простым (исключенным) xaml:

<UserControl x:Class="WpfControlLibrary1.TinyTimeSpanControl"  x:Name="root">
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto" />
        <ColumnDefinition Width="Auto" />
        <ColumnDefinition Width="Auto" />
    </Grid.ColumnDefinitions>
    <Slider Name="SecondsSlider"
            Width="120"
            Height="23"
            HorizontalAlignment="Left"
            VerticalAlignment="Top"
            LargeChange="5"
            SelectionStart="0"
            SmallChange="1"
            Value="{Binding Path=Seconds,
                            ElementName=root}" SelectionEnd="59" Maximum="59" />
    <Label Name="label1"
           Grid.Column="1"
           Content="{Binding ElementName=SecondsSlider,
                             Path=Value}" />
    <Label Name="label2"
           Grid.Column="2"
           Content="Seconds" />
</Grid>
</UserControl>

Привязка в элементе управления работает нормально.

Теперь, когда я скомпилирую это, добавьте TinyTimeSpanControl к одному из моих окон (elided):

    <Window x:Class="WpfControls.MainWindow"
            xmlns:my="clr-namespace:WpfControlLibrary1;assembly=WpfControlLibrary1"
            x:Name="root"
            Closing="root_Closing">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="142*" />
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition Width="Auto" />
            </Grid.ColumnDefinitions>
            <my:TinyTimeSpanControl Name="tinyTimeSpanControl1"
                                    HorizontalAlignment="Left"
                                    VerticalAlignment="Top"
                                    Value="{Binding ElementName=root,
                                                    Path=TheTime}" />
            <Label Name="label1"
                   Grid.Column="1"
                   Content="{Binding ElementName=tinyTimeSpanControl1,
                                     Path=Value}" />
            <Label Name="label2"
                   Grid.Column="2"
                   Content="{Binding ElementName=root,
                                     Path=TheTime}" />

        </Grid>
    </Window>

, где мое главное окно:

public partial class MainWindow : Window, INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    private void RaisePropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    private TimeSpan _theTime = new TimeSpan(0, 0, 33);
    public TimeSpan TheTime
    {
        get
        {
            return _theTime;
        }
        set
        {
            if (_theTime == value)
                return;

            _theTime = value;
            RaisePropertyChanged("TheTime");
        }
    }

привязка данных частично работает:

  • tinyTimeSpanControl1 изначально установлено в значение свойства TheTime в моем коде позади моего главного окна
  • tinyTimeSpanControl1 обновления label1, когдаползунок перемещен.

Но не работает:

  • при перемещении ползунка label2 остается установленным в исходную версию TheTime

Установка точки останова на событие Window_closing показывает, что TheTime не изменилась.

Я пропустил какое-то событие, которое мне нужно вызвать в моем UserControl?

Спасибо, и еще раз извиняюсь за все xaml (это также минимальный случай).

1 Ответ

2 голосов
/ 10 января 2012

Это проблема:

Value = new TimeSpan(t.Hours, t.Minutes, _seconds);

Это очищает привязку, которую вы установили в своем окне, и просто устанавливает значение.В коде UserControl вы не должны использовать SetValue, но SetCurrentValue, который сохраняет привязки к свойству нетронутыми.

Некоторые другие вещи также могут быть отключены, что я не сделалувидеть еще ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...