[英]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.