使用样式时无法获取属性值

时间:2010-12-15 07:53:00

标签: wpf wpf-controls binding wpfdatagrid

我有一个自定义控件,我将模板应用于。在自定义控件内部,我定义了绑定到样式内模板控件的属性。如果我订阅了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 :(得分:0)

尝试使用OnApplyTemplate事件而不是加载事件

public override void OnApplyTemplate()

答案 1 :(得分:0)

绑定评估在构建整个Visual Tree之后的加载过程中稍后进行。不要依赖单个事件来收集值,只需在DependencyProperties上使用PropertyChanged处理程序,您已经确认它们已经为您提供了预期的值。

您还可以简化ColumnEntity以使用ColumnEntity="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Column}"