C# WPF-具有多重绑定和不同数据上下文的自定义工具提示

C# WPF-具有多重绑定和不同数据上下文的自定义工具提示,c#,wpf,mvvm,data-binding,C#,Wpf,Mvvm,Data Binding,我想在WPF(C#-MVVM)中创建一个带有自定义两行工具提示的UserControl 在视图中,我有一个列表框,其中包含一个ItemSource和一个自定义ItemTemplate,用于设置上一个工具提示,在运行时只显示第一行,而第二行是空的字符串。实际上,问题是工具提示的第二行,其中我使用了带转换器的多绑定;在try/catch中失败的转换器返回空字符串 我知道异常是由一个null的值生成的,而它应该是一个int不可为null的值,但我不明白为什么。 编辑:我说错了null;问题是转换器触发

我想在WPF(C#-MVVM)中创建一个带有自定义两行工具提示的
UserControl

在视图中,我有一个
列表框
,其中包含一个
ItemSource
和一个自定义
ItemTemplate
,用于设置上一个
工具提示
,在运行时只显示第一行,而第二行是空的
字符串
。实际上,问题是
工具提示的第二行
,其中我使用了带转换器的
多绑定
;在
try/catch
中失败的转换器返回空
字符串

我知道异常是由一个
null
的值生成的,而它应该是一个
int
不可为null的值,但我不明白为什么。
编辑:我说错了
null
;问题是转换器触发强制转换异常是因为
dependencProperty UnsetValue
,我不知道为什么

此处转换器代码:

我不明白为什么
文本块
工具提示
之外有效,为什么在
工具提示
内部无效。
如何解决此问题?

绑定失败,因为
UserControl
不是
工具提示的可视祖先

您可以将
网格
标记
属性绑定到
小数
属性,然后使用
工具提示
放置目标
属性绑定到
标记
属性:

<DataTemplate>
    <Grid Tag="{Binding Decimals, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}">
        <Grid.ToolTip>
            <ToolTip>
                <StackPanel>
                    <TextBlock Text="{Binding Description}"/>
                    <TextBlock>
                        <TextBlock.Text>
                            <MultiBinding Converter="{cv_ToString:FromDecimal_MVConverter}">
                                <Binding Path="Value"/>
                                <Binding Path="PlacementTarget.Tag" RelativeSource="{RelativeSource FindAncestor, AncestorType=ToolTip}"/>
                            </MultiBinding>
                        </TextBlock.Text>
                    </TextBlock>
                </StackPanel>
            </ToolTip>
        </Grid.ToolTip>
        ...
    </Grid>
</DataTemplate>

...

我是如何解决的:
我已经阅读了@Sinatr的评论,最后我发现了如何避免这个问题。


...
...
...

在这种情况下,
BindingProxy
直接绑定到
dependencProperty小数
,而不是
DataContext

还是不行!你能解释一下你的第一行吗?如果我有多个属性,如何避免问题?如果我只能有一个
标记
?@MaxAquila,附加的依赖属性可能会有所帮助。另一种可能是使用,这种技术允许您命名和访问多个数据上下文。@Sinatr,谢谢,我已经解决了
BindingProxy
@MaxAquila的问题,虽然很小,但很重要:请将答案作为单独的帖子发布。是的。
...
<ListBox ItemsSource="{Binding Values, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <Grid>
                <ToolTipService.ToolTip>
                    <StackPanel>
                        <TextBlock Text="{Binding Description}"/>
                        <TextBlock>
                            <TextBlock.Text>
                                <MultiBinding Converter="{cv_ToString:FromDecimal_MVConverter}">
                                    <Binding Path="Value"/>
                                    <Binding Path="Decimals" RelativeSource="{RelativeSource FindAncestor, AncestorType=UserControl}"/>
                                </MultiBinding>
                            </TextBlock.Text>
                        </TextBlock>
                    </StackPanel>
                </ToolTipService.ToolTip>
                <TextBlock Foreground="{Binding Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}">
                    <TextBlock.Text>
                        <MultiBinding Converter="{cv_ToString:FromDecimal_MVConverter}">
                            <Binding Path="Value"/>
                            <Binding Path="Decimals" RelativeSource="{RelativeSource FindAncestor, AncestorType=UserControl}"/>
                        </MultiBinding>
                    </TextBlock.Text>
                </TextBlock>
            </Grid>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>
...
public static readonly DependencyProperty DecimalsProperty = DependencyProperty.RegisterAttached("Decimals", typeof(int), typeof(ucMyUserControl), new FrameworkPropertyMetadata(2) { BindsTwoWayByDefault = true });

public int Decimals
{
    get { return (int)GetValue(DecimalsProperty); }
    set { SetValue(DecimalsProperty, value); }
}
<DataTemplate>
    <Grid Tag="{Binding Decimals, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}">
        <Grid.ToolTip>
            <ToolTip>
                <StackPanel>
                    <TextBlock Text="{Binding Description}"/>
                    <TextBlock>
                        <TextBlock.Text>
                            <MultiBinding Converter="{cv_ToString:FromDecimal_MVConverter}">
                                <Binding Path="Value"/>
                                <Binding Path="PlacementTarget.Tag" RelativeSource="{RelativeSource FindAncestor, AncestorType=ToolTip}"/>
                            </MultiBinding>
                        </TextBlock.Text>
                    </TextBlock>
                </StackPanel>
            </ToolTip>
        </Grid.ToolTip>
        ...
    </Grid>
</DataTemplate>
<UserControl.Resources>
    <local:BindingProxy x:Key="BP_Decimals" Data="{Binding Decimals, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}"/>
</UserControl.Resources>
...
    <DataTemplate>
        <Grid>
            <Grid.ToolTip>
                <StackPanel>
                    <TextBlock Text="{Binding Description}"/>
                    <TextBlock>
                        <TextBlock.Text>
                            <MultiBinding Converter="{cv_ToString:FromDecimal_MVConverter}">
                                <Binding Path="Value"/>
                                <Binding Path="Data" Source="{StaticResource BP_Decimals}"/>
                            </MultiBinding>
                        </TextBlock.Text>
                    </TextBlock>
                </StackPanel>
            </Grid.ToolTip>
            ...
        </Grid>
    </DataTemplate>
...