C# 将工具提示绑定到自定义控件内的DependencyProperty

C# 将工具提示绑定到自定义控件内的DependencyProperty,c#,wpf,data-binding,dependency-properties,C#,Wpf,Data Binding,Dependency Properties,我正在尝试将一些值绑定到DataGridTextColumn的CellStyle中的ToolTipService.ShowDuration和一些其他工具提示属性 通常,我是这样做的: <UserControl ...namespace declarations...> <UserControl.Resources> <mycontrols:BindingProxy x:Key="proxy" Data="{Binding MySett

我正在尝试将一些值绑定到
DataGridTextColumn
CellStyle
中的
ToolTipService.ShowDuration
和一些其他工具提示属性

通常,我是这样做的:

<UserControl
    ...namespace declarations...>
    <UserControl.Resources>
        <mycontrols:BindingProxy x:Key="proxy" Data="{Binding MySettings}"/>
    </UserControl.Resources>
    <DataGrid>
        <DataGridTextColumn
            Binding="{Binding SomeBinding}">
            <DataGridTextColumn.CellStyle>
                <Style 
                    TargetType="DataGridCell" 
                    BasedOn="{StaticResource ResourceKey={x:Type DataGridCell}}">
                    <Setter 
                        Property="ToolTipService.ShowDuration" 
                        Value="{Binding Data.ToolTipDuration, Source={StaticResource proxy}}"/>
                    <Setter Property="ToolTip">
                        <Setter.Value>
                            <TextBlock 
                                Text="{Binding SomeBinding}" 
                                MaxWidth="{Binding Data.ToolTipMaxWidth, Source={StaticResource proxy}}" 
                                TextWrapping="Wrap" TextTrimming="CharacterEllipsis"/>
                        </Setter.Value>
                    </Setter>
                </Style>
            </DataGridTextColumn.CellStyle>
        </DataGridTextColumn>
    </DataGrid>
</UserControl>
public class BindingProxy : Freezable
    {
        protected override Freezable CreateInstanceCore()
        {
            return new BindingProxy();
        }

        public object Data
        {
            get { return (object)GetValue(DataProperty); }
            set { SetValue(DataProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Data.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DataProperty =
            DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null));
    }
<DataGridTextColumn
    x:Class="Test.MyControls.DataGridLargeTextColumn"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:Test.MyControls">
    <DataGridTextColumn.CellStyle>
        <Style 
            TargetType="DataGridCell" 
            BasedOn="{StaticResource ResourceKey={x:Type DataGridCell}}">
            <Setter 
                Property="ToolTipService.ShowDuration" 
                Value="{Binding ToolTipDuration}"/>
            <Setter Property="ToolTip">
                <Setter.Value>
                    <TextBlock 
                        Text="{Binding SomeBinding}" 
                        MaxWidth="{Binding ToolTipWidth}" 
                        TextWrapping="Wrap" TextTrimming="CharacterEllipsis"/>
                </Setter.Value>
            </Setter>
        </Style>
    </DataGridTextColumn.CellStyle>
</DataGridTextColumn>
<UserControl
    ...namespace declarations...>
    <UserControl.Resources>
        <mycontrols:BindingProxy x:Key="proxy" Data="{Binding MySettings}"/>
    </UserControl.Resources>
    <DataGrid>
        <DataGrid.Columns>
            <mycontrols:DataGridLargeTextColumn
                Binding="{Binding SomeBinding}"
                ToolTipShowDuration="{Binding Data.ToolTipDuration, Source={StaticResource proxy}}"
                ToolTipWidth="{Binding Data.ToolTipMaxWidth, Source={StaticResource proxy}}"/>
        </DataGrid.Columns>
    </DataGrid>
</UserControl>
<Setter Property="ToolTip">
    <Setter.Value>
        <ToolTip DataContext="{Binding Path=PlacementTarget, RelativeSource={x:Static RelativeSource.Self}}">
            <TextBlock 
                Text="{Binding DataContext.SomeBinding}"
                Width="{Binding Column.ToolTipWidth}" />
        </ToolTip>
    </Setter.Value>
</Setter>
到目前为止,一切都按预期进行。但我想重新使用这个DataGridTextColumn,所以我创建了如下新文件:

<UserControl
    ...namespace declarations...>
    <UserControl.Resources>
        <mycontrols:BindingProxy x:Key="proxy" Data="{Binding MySettings}"/>
    </UserControl.Resources>
    <DataGrid>
        <DataGridTextColumn
            Binding="{Binding SomeBinding}">
            <DataGridTextColumn.CellStyle>
                <Style 
                    TargetType="DataGridCell" 
                    BasedOn="{StaticResource ResourceKey={x:Type DataGridCell}}">
                    <Setter 
                        Property="ToolTipService.ShowDuration" 
                        Value="{Binding Data.ToolTipDuration, Source={StaticResource proxy}}"/>
                    <Setter Property="ToolTip">
                        <Setter.Value>
                            <TextBlock 
                                Text="{Binding SomeBinding}" 
                                MaxWidth="{Binding Data.ToolTipMaxWidth, Source={StaticResource proxy}}" 
                                TextWrapping="Wrap" TextTrimming="CharacterEllipsis"/>
                        </Setter.Value>
                    </Setter>
                </Style>
            </DataGridTextColumn.CellStyle>
        </DataGridTextColumn>
    </DataGrid>
</UserControl>
public class BindingProxy : Freezable
    {
        protected override Freezable CreateInstanceCore()
        {
            return new BindingProxy();
        }

        public object Data
        {
            get { return (object)GetValue(DataProperty); }
            set { SetValue(DataProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Data.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DataProperty =
            DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null));
    }
<DataGridTextColumn
    x:Class="Test.MyControls.DataGridLargeTextColumn"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:Test.MyControls">
    <DataGridTextColumn.CellStyle>
        <Style 
            TargetType="DataGridCell" 
            BasedOn="{StaticResource ResourceKey={x:Type DataGridCell}}">
            <Setter 
                Property="ToolTipService.ShowDuration" 
                Value="{Binding ToolTipDuration}"/>
            <Setter Property="ToolTip">
                <Setter.Value>
                    <TextBlock 
                        Text="{Binding SomeBinding}" 
                        MaxWidth="{Binding ToolTipWidth}" 
                        TextWrapping="Wrap" TextTrimming="CharacterEllipsis"/>
                </Setter.Value>
            </Setter>
        </Style>
    </DataGridTextColumn.CellStyle>
</DataGridTextColumn>
<UserControl
    ...namespace declarations...>
    <UserControl.Resources>
        <mycontrols:BindingProxy x:Key="proxy" Data="{Binding MySettings}"/>
    </UserControl.Resources>
    <DataGrid>
        <DataGrid.Columns>
            <mycontrols:DataGridLargeTextColumn
                Binding="{Binding SomeBinding}"
                ToolTipShowDuration="{Binding Data.ToolTipDuration, Source={StaticResource proxy}}"
                ToolTipWidth="{Binding Data.ToolTipMaxWidth, Source={StaticResource proxy}}"/>
        </DataGrid.Columns>
    </DataGrid>
</UserControl>
<Setter Property="ToolTip">
    <Setter.Value>
        <ToolTip DataContext="{Binding Path=PlacementTarget, RelativeSource={x:Static RelativeSource.Self}}">
            <TextBlock 
                Text="{Binding DataContext.SomeBinding}"
                Width="{Binding Column.ToolTipWidth}" />
        </ToolTip>
    </Setter.Value>
</Setter>
这不起作用,因为工具提示有自己的视觉树,但由于我没有地方放置代理,我不知道如何使它工作,或者它是否可能。我发现了,而且它似乎在正确的轨道上,但是,我试图像这样实现它,但没有运气:

<Setter 
    Property="ToolTipService.ShowDuration"
    Value="{Binding Path=PlacementTarget.(local:DataGridLargeTextColumn.ToolTipDuration), RelativeSource={RelativeSource Self}}"/>
<Setter Property="ToolTip">
    <Setter.Value>
        <TextBlock 
            Text="{Binding Path=PlacementTarget.(local:DataGridLargeTextColumn.SomeBinding), RelativeSource={RelativeSource Self}}" 
            MaxWidth="{Binding Path=PlacementTarget.(local:DataGridLargeTextColumn.ToolTipWidth), RelativeSource={RelativeSource Self}}" 
            TextWrapping="Wrap" TextTrimming="CharacterEllipsis"/>
    </Setter.Value>
</Setter>
我使用的控件是这样的:

<UserControl
    ...namespace declarations...>
    <UserControl.Resources>
        <mycontrols:BindingProxy x:Key="proxy" Data="{Binding MySettings}"/>
    </UserControl.Resources>
    <DataGrid>
        <DataGridTextColumn
            Binding="{Binding SomeBinding}">
            <DataGridTextColumn.CellStyle>
                <Style 
                    TargetType="DataGridCell" 
                    BasedOn="{StaticResource ResourceKey={x:Type DataGridCell}}">
                    <Setter 
                        Property="ToolTipService.ShowDuration" 
                        Value="{Binding Data.ToolTipDuration, Source={StaticResource proxy}}"/>
                    <Setter Property="ToolTip">
                        <Setter.Value>
                            <TextBlock 
                                Text="{Binding SomeBinding}" 
                                MaxWidth="{Binding Data.ToolTipMaxWidth, Source={StaticResource proxy}}" 
                                TextWrapping="Wrap" TextTrimming="CharacterEllipsis"/>
                        </Setter.Value>
                    </Setter>
                </Style>
            </DataGridTextColumn.CellStyle>
        </DataGridTextColumn>
    </DataGrid>
</UserControl>
public class BindingProxy : Freezable
    {
        protected override Freezable CreateInstanceCore()
        {
            return new BindingProxy();
        }

        public object Data
        {
            get { return (object)GetValue(DataProperty); }
            set { SetValue(DataProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Data.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DataProperty =
            DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null));
    }
<DataGridTextColumn
    x:Class="Test.MyControls.DataGridLargeTextColumn"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:Test.MyControls">
    <DataGridTextColumn.CellStyle>
        <Style 
            TargetType="DataGridCell" 
            BasedOn="{StaticResource ResourceKey={x:Type DataGridCell}}">
            <Setter 
                Property="ToolTipService.ShowDuration" 
                Value="{Binding ToolTipDuration}"/>
            <Setter Property="ToolTip">
                <Setter.Value>
                    <TextBlock 
                        Text="{Binding SomeBinding}" 
                        MaxWidth="{Binding ToolTipWidth}" 
                        TextWrapping="Wrap" TextTrimming="CharacterEllipsis"/>
                </Setter.Value>
            </Setter>
        </Style>
    </DataGridTextColumn.CellStyle>
</DataGridTextColumn>
<UserControl
    ...namespace declarations...>
    <UserControl.Resources>
        <mycontrols:BindingProxy x:Key="proxy" Data="{Binding MySettings}"/>
    </UserControl.Resources>
    <DataGrid>
        <DataGrid.Columns>
            <mycontrols:DataGridLargeTextColumn
                Binding="{Binding SomeBinding}"
                ToolTipShowDuration="{Binding Data.ToolTipDuration, Source={StaticResource proxy}}"
                ToolTipWidth="{Binding Data.ToolTipMaxWidth, Source={StaticResource proxy}}"/>
        </DataGrid.Columns>
    </DataGrid>
</UserControl>
<Setter Property="ToolTip">
    <Setter.Value>
        <ToolTip DataContext="{Binding Path=PlacementTarget, RelativeSource={x:Static RelativeSource.Self}}">
            <TextBlock 
                Text="{Binding DataContext.SomeBinding}"
                Width="{Binding Column.ToolTipWidth}" />
        </ToolTip>
    </Setter.Value>
</Setter>
但当我试图绑定它时,它不起作用,这正是我试图实现的:

<myControls:DataGridLargeTextColumn
    Binding="{Binding SomeBinding}"
    ToolTipText="{Binding SomeOtherPropertyBinding}" 
    ToolTipShowDuration="{Binding Data.ToolTipDuration, Source={StaticResource proxy}}"
    ToolTipWidth="{Binding Data.ToolTipMaxWidth, Source={StaticResource proxy}}"/>

默认情况下,工具提示的DataContext设置为单元格的DataContext。但是,您正试图绑定到单元格列中的依赖项属性,因此您必须更改DataContext以指向单元格本身,然后在需要访问数据时显式引用
DataContext
,在需要访问DataGridLargeTextColumn中的DPs时显式引用
column

换句话说,除了工具提示的内容外,还要显式声明工具提示,并设置其DataContext,如下所示:

<UserControl
    ...namespace declarations...>
    <UserControl.Resources>
        <mycontrols:BindingProxy x:Key="proxy" Data="{Binding MySettings}"/>
    </UserControl.Resources>
    <DataGrid>
        <DataGridTextColumn
            Binding="{Binding SomeBinding}">
            <DataGridTextColumn.CellStyle>
                <Style 
                    TargetType="DataGridCell" 
                    BasedOn="{StaticResource ResourceKey={x:Type DataGridCell}}">
                    <Setter 
                        Property="ToolTipService.ShowDuration" 
                        Value="{Binding Data.ToolTipDuration, Source={StaticResource proxy}}"/>
                    <Setter Property="ToolTip">
                        <Setter.Value>
                            <TextBlock 
                                Text="{Binding SomeBinding}" 
                                MaxWidth="{Binding Data.ToolTipMaxWidth, Source={StaticResource proxy}}" 
                                TextWrapping="Wrap" TextTrimming="CharacterEllipsis"/>
                        </Setter.Value>
                    </Setter>
                </Style>
            </DataGridTextColumn.CellStyle>
        </DataGridTextColumn>
    </DataGrid>
</UserControl>
public class BindingProxy : Freezable
    {
        protected override Freezable CreateInstanceCore()
        {
            return new BindingProxy();
        }

        public object Data
        {
            get { return (object)GetValue(DataProperty); }
            set { SetValue(DataProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Data.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DataProperty =
            DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null));
    }
<DataGridTextColumn
    x:Class="Test.MyControls.DataGridLargeTextColumn"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:Test.MyControls">
    <DataGridTextColumn.CellStyle>
        <Style 
            TargetType="DataGridCell" 
            BasedOn="{StaticResource ResourceKey={x:Type DataGridCell}}">
            <Setter 
                Property="ToolTipService.ShowDuration" 
                Value="{Binding ToolTipDuration}"/>
            <Setter Property="ToolTip">
                <Setter.Value>
                    <TextBlock 
                        Text="{Binding SomeBinding}" 
                        MaxWidth="{Binding ToolTipWidth}" 
                        TextWrapping="Wrap" TextTrimming="CharacterEllipsis"/>
                </Setter.Value>
            </Setter>
        </Style>
    </DataGridTextColumn.CellStyle>
</DataGridTextColumn>
<UserControl
    ...namespace declarations...>
    <UserControl.Resources>
        <mycontrols:BindingProxy x:Key="proxy" Data="{Binding MySettings}"/>
    </UserControl.Resources>
    <DataGrid>
        <DataGrid.Columns>
            <mycontrols:DataGridLargeTextColumn
                Binding="{Binding SomeBinding}"
                ToolTipShowDuration="{Binding Data.ToolTipDuration, Source={StaticResource proxy}}"
                ToolTipWidth="{Binding Data.ToolTipMaxWidth, Source={StaticResource proxy}}"/>
        </DataGrid.Columns>
    </DataGrid>
</UserControl>
<Setter Property="ToolTip">
    <Setter.Value>
        <ToolTip DataContext="{Binding Path=PlacementTarget, RelativeSource={x:Static RelativeSource.Self}}">
            <TextBlock 
                Text="{Binding DataContext.SomeBinding}"
                Width="{Binding Column.ToolTipWidth}" />
        </ToolTip>
    </Setter.Value>
</Setter>

如果将
BindingProxy
移动到
DataGridTextColumn.Resources
block中,它不起作用吗?如果我没有弄错
DataGridTextColumn
没有
Resources
块,那是我尝试做的第一件事哦!当然没有,对不起。回答如下。我已经设法让它按照你写的方式工作,但我还有两个问题。1.为什么我不能将
文本
绑定到
列。ToolTipText
?我试过了,但效果很奇怪。当我将
ToolTipText
设置为string literal时,它可以工作,但当我将它绑定到同一个值列时,它就不工作了,该值列本身的
Binding
被赋值;2.这将如何转化为
ToolTipService.ShowDuration
?显然,我仍然需要访问DP的
,但我尝试了几种不同的方法,但没有成功。由于它是抽象的,我不能明确地声明它当你说
文本
绑定“以一种非常奇怪的方式”工作时,你是什么意思?我知道我的解决方案代码与您的问题代码100%不匹配,如果您发布到目前为止实现的更新,我很乐意再看一看。可能只是模式和/或更新标志有问题。请尝试在那些损坏的绑定上设置模式,我想您会发现WPF正在混淆您尝试绑定的方向。字符串文字是显而易见的,因为它只能走一条路,其他绑定则不然。我会提供更多的帮助,但是代码现在太复杂了,缺少了太多的片段。如果你仍然陷在困境中,我很乐意看到mcve,这是一件非常简单的事情。