[英]WPF - custom ToolTip with MultiBinding and different DataContexts
我想用自定义的两行ToolTip
在 WPF (C# - MVVM) 中创建一个UserControl
。
在视图中,我有一个带有ItemSource
的ListBox
和一个自定义ItemTemplate
用于设置在运行时仅显示第一行而第二行是空string
的前一个ToolTip
。 确实,问题出在ToolTip
的第二行,我在其中使用了带有转换器的MultiBinding
; 在try/catch
中失败的转换器返回空string
。
我知道异常是由一个null
值生成的,而它应该是一个不可为null
的int
,但我不明白为什么。
编辑:我说null
是错误的; 问题是转换器由于DependencyProperty UnsetValue
转换异常,我不知道为什么。
这里转换器代码:
public class FromDecimal_MVConverter : Base_MVConverter
{
public override object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
try
{
// Default are 2 decimals
if (values.Length == 2)
{
int decimals;
switch ((int)values[1])
{
case int dec when dec < 0:
decimals = 0;
break;
case int dec when dec > 99:
decimals = 99;
break;
default:
decimals = (int)values[1];
break;
}
return ((decimal)values[0]).ToString("N" + decimals.ToString());
}
else
{
return ((decimal)values[0]).ToString("N2");
}
}
catch
{
return string.Empty;
}
}
public override object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
这里的XAML代码:
...
<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>
...
如您所见, Value
是ObservableCollection Values
对象的属性。 Decimals
和Values
是与它们的依赖属性相关联的代码中的属性。
这里的Decimals
定义:
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); }
}
我不明白为什么在ToolTip
之外的TextBlock
可以工作,为什么在ToolTip
内部不行。 我该如何解决问题?
绑定失败,因为UserControl
不是ToolTip
的视觉祖先。
您可以在绑定Tag
的财产Grid
的Decimals
属性,然后绑定到Tag
使用属性PlacementTarget
的财产ToolTip
:
<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的评论,最后我找到了如何避免这个问题。
<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>
...
在这种情况下, BindingProxy
直接绑定到DependencyProperty Decimals
而不是DataContext
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.