Невозможно получить значение свойства при использовании стилей - PullRequest
0 голосов
/ 15 декабря 2010

У меня есть пользовательский элемент управления, к которому я применяю шаблон. Внутри пользовательского элемента управления я определил свойства, которые привязаны к шаблонному элементу управления внутри стиля. Если я подписан на событие Loaded и пытаюсь получить свойства, они имеют значение null. Однако, если я буду использовать OnPropertyChanged, у них есть значения. Может кто-нибудь объяснить, пожалуйста, почему это так. Пожалуйста, посмотрите на свойство ColumnEntity.

Спасибо.

Я удалил некоторые детали для безопасности

 <!-- This code is based on http://www.codeproject.com/KB/WPF/DataGridFilterLibrary.aspx -->

  <Style TargetType="{x:Type local:DataGridColumnFilter}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:DataGridColumnFilter}">
                <Border Background ="{TemplateBinding Background}" 
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}">
                    <TextBox VerticalAlignment="Top" VerticalContentAlignment="Center" Background="AliceBlue"
                        Text="{Binding 
                            RelativeSource={RelativeSource AncestorType={x:Type local:DataGridColumnFilter}}, 
                            Path=QueryEntity.Text, Mode=OneWayToSource, UpdateSourceTrigger=Explicit}">
                    </TextBox>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<Style x:Key="{ComponentResourceKey 
    TypeInTargetAssembly={x:Type local:DataGridColumnFilter}, ResourceId=DataGridHeaderFilterControlStyle}" 
    TargetType="{x:Type DataGridColumnHeader}">

    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type DataGridColumnHeader}">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition />
                        <RowDefinition />
                    </Grid.RowDefinitions>

                    <local:DataGridColumnFilter Grid.Row="0"
                        DataGridEntity="{Binding 
                            RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=.}" 
                        ColumnEntity="{Binding 
                            RelativeSource={RelativeSource AncestorType={x:Type DataGridColumnHeader}}, Path=Column}"
                        ItemsSourceEntity ="{Binding 
                            RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, 
                            Path=ItemsSource}"/>

                    <theme:DataGridHeaderBorder Grid.Row="1" 
                            SortDirection  ="{TemplateBinding SortDirection}"
                            IsHovered      ="{TemplateBinding IsMouseOver}"
                            IsPressed      ="{TemplateBinding IsPressed}"
                            IsClickable    ="{TemplateBinding CanUserSort}"
                            Background     ="{TemplateBinding Background}"
                            BorderBrush    ="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}"
                            Padding        ="{TemplateBinding Padding}"
                            SeparatorBrush ="{TemplateBinding SeparatorBrush}"
                            SeparatorVisibility="{TemplateBinding SeparatorVisibility}">

                        <TextBlock Grid.Row="1" TextWrapping="Wrap" 
                            Text               ="{TemplateBinding Content}" 
                            SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                            VerticalAlignment  ="{TemplateBinding VerticalContentAlignment}"
                            HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}">
                        </TextBlock>
                    </theme:DataGridHeaderBorder>

                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

public class DataGridColumnFilter : Control
{
    static DataGridColumnFilter()
    {
        DefaultStyleKeyProperty.OverrideMetadata(
            typeof(DataGridColumnFilter), new FrameworkPropertyMetadata(typeof(DataGridColumnFilter)));
    }

    public DataGridColumnFilter()
    {
        this.Loaded += new RoutedEventHandler(DataGridColumnFilter_Loaded);
    }

    void DataGridColumnFilter_Loaded(object sender, RoutedEventArgs e)
    {
        // here is would be null!
        var controller = ColumnEntity;
    }
    // For some reason this seems to be the only place to access the ColumnEntity
           protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
    {
        if (e.Property == ItemsSourceEntityProperty && e.OldValue != e.NewValue && null != DataGridEntity && ColumnEntity is DataGridColumn)
        {
             // here it works fine. The property has a proper value
              var controller = ColumnEntity;
        }

        base.OnPropertyChanged(e);
    }

    #region Properties

    public Query QueryEntity
    {
        get { return (Query)GetValue(QueryEntityProperty); }
        set { SetValue(QueryEntityProperty, value); }
    }

    public static readonly DependencyProperty QueryEntityProperty =
        DependencyProperty.Register("QueryEntity", typeof(Query), typeof(DataGridColumnFilter));

    public DataGridColumn ColumnEntity
    {
        get { return (DataGridColumn)GetValue(ColumnEntityProperty); }
        set { SetValue(ColumnEntityProperty, value); }
    }

    public static readonly DependencyProperty ColumnEntityProperty =
        DependencyProperty.Register("ColumnEntity", typeof(DataGridColumn), typeof(DataGridColumnFilter));

    public DataGrid DataGridEntity
    {
        get { return (DataGrid)GetValue(DataGridEntityProperty); }
        set { SetValue(DataGridEntityProperty, value); }
    }

    public static readonly DependencyProperty DataGridEntityProperty =
        DependencyProperty.Register("DataGridEntity", typeof(DataGrid), typeof(DataGridColumnFilter));

    public IEnumerable ItemsSourceEntity
    {
        get { return (IEnumerable)GetValue(ItemsSourceEntityProperty); }
        set { SetValue(ItemsSourceEntityProperty, value); }
    }

    public static readonly DependencyProperty ItemsSourceEntityProperty =
        DependencyProperty.Register("ItemsSourceEntity", typeof(IEnumerable), typeof(DataGridColumnFilter));

    #endregion
}

Ответы [ 2 ]

0 голосов
/ 15 декабря 2010

Оценка привязки происходит позже в процессе загрузки после того, как все дерево визуалов было построено. Вместо того чтобы полагаться на одно событие для сбора значений, просто используйте обработчики PropertyChanged в свойствах DependencyProperties, которые, как вы уже подтвердили, дают ожидаемые значения.

Вы также можете упростить использование ColumnEntity ColumnEntity="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Column}"

0 голосов
/ 15 декабря 2010

попробуйте использовать событие OnApplyTemplate вместо загруженного события

public override void OnApplyTemplate()

...