[英]WPF - custom ToolTip with MultiBinding and different DataContexts
I want to make a UserControl
in WPF (C# - MVVM) with a custom two-lines ToolTip
.我想用自定义的两行ToolTip
在 WPF (C# - MVVM) 中创建一个UserControl
。
In the View I have a ListBox
with an ItemSource
and a custom ItemTemplate
where to set the previous ToolTip
that at runtime shows only the first line while the second one is an empty string
.在视图中,我有一个带有ItemSource
的ListBox
和一个自定义ItemTemplate
用于设置在运行时仅显示第一行而第二行是空string
的前一个ToolTip
。 Indeed the problem is the second line of the ToolTip
where I use a MultiBinding
with a converter;确实,问题出在ToolTip
的第二行,我在其中使用了带有转换器的MultiBinding
; converter that fails in try/catch
returning an empty string
.在try/catch
中失败的转换器返回空string
。
I know that the exception is generated by a value that is null
while it should be an int
not nullable, but I don't understand why.我知道异常是由一个null
值生成的,而它应该是一个不可为null
的int
,但我不明白为什么。
EDIT: I was wrong saying null
;编辑:我说null
是错误的; the problem is that the converter strikes a cast exception because of DependencyProperty UnsetValue
, I don't know why.问题是转换器由于DependencyProperty UnsetValue
转换异常,我不知道为什么。
Here Converter code:这里转换器代码:
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();
}
}
Here XAML code:这里的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>
...
As you can see Value
is a property of an object in ObservableCollection Values
.如您所见, Value
是ObservableCollection Values
对象的属性。 Decimals
and Values
are properties in code behind associated to their dependency properties. Decimals
和Values
是与它们的依赖属性相关联的代码中的属性。
Here Decimals
definition:这里的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); }
}
I don't understand why for the TextBlock
outside the ToolTip
it works and why inside the ToolTip
not.我不明白为什么在ToolTip
之外的TextBlock
可以工作,为什么在ToolTip
内部不行。 How can I resolve the problem?我该如何解决问题?
The binding fails because the UserControl
is not a visual ancestor of the ToolTip
.绑定失败,因为UserControl
不是ToolTip
的视觉祖先。
You could bind the Tag
property of the Grid
to the Decimals
property and then bind to the Tag
property using the PlacementTarget
property of the 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>
How I have solved:我是如何解决的:
I have read the comment of @Sinatr about BindingProxy and finally I have found how to avoid the problem.我已经阅读了@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>
...
In this case the BindingProxy
is binded directly to the DependencyProperty Decimals
and not to DataContext
.在这种情况下, BindingProxy
直接绑定到DependencyProperty Decimals
而不是DataContext
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.