WPF:ValueConverter (IValueConverter) 不起作用
WPF: ValueConverter (IValueConverter) does not work
我有一个 Window
class,其中我有几个 TextBlock
元素应该接收 Background
颜色 Binding
属性。第一个 "Converter binding" 工作正常并且完成了预期的一切。今天我尝试用另一个 Converter
实现另一个 "Converter binding",但它不起作用:
(我省略了 ConvertBack
方法,因为它们在这里不是必需的):
namespace InsightTool.Gui.Helper {
[ValueConversion(typeof(double), typeof(Brush))]
public class AverageExecutionTimeToColorConverter : IValueConverter {
public object Convert (object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
double val;
double.TryParse(value.ToString(), out val);
if (val >= 10000) {
return Brushes.Red;
} else if (val >= 5000) {
return Brushes.Orange;
} else {
return Brushes.Green;
}
}
}
[ValueConversion(typeof(int), typeof(Brush))]
public class ThreadsAvailableCountToColorConverter : IValueConverter {
public object Convert (object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
int val;
int.TryParse(value.ToString(), out val);
if (val < 100) {
return Brushes.Red;
} else if (val < 200) {
return Brushes.Orange;
} else if (val < 500) {
return Brushes.Yellow;
} else {
return Brushes.Green;
}
}
}
}
在 Window
class 中,我使用了以下两个转换:
<Window ...
x:Name="Main"
xmlns:Base="clr-namespace:InsightTool.Gui.Helper">
<Window.Resources>
<Base:ThreadsAvailableCountToColorConverter x:Key="ThreadsAvailableCntConverter"/>
<Base:AverageExecutionTimeToColorConverter x:Key="AvgExecutionTimeConverter"/>
</Window.Resources>
<!-- This one works fine-->
<TextBlock Width="10" Height="10" VerticalAlignment="Center" Background="{Binding ExecutionTimeAverage, Converter={StaticResource AvgExecutionTimeConverter}, ElementName=UCExecutionTimes}"/>
<!-- This one does not work-->
<TextBlock Width="10" Height="10" VerticalAlignment="Center" Background="{Binding ThreadsAvailableCount, Converter={StaticResource ThreadsAvailableCntConverter}, ElementName=Main}"/>
</Window>
DependencyProperties
的声明:
public partial class UserControlExecutionTimes : UserControl {
public static readonly DependencyProperty ExecutionTimeAverageProperty =
DependencyProperty.Register("ExecutionTimeAverage", typeof(double), typeof(MainWindow), new FrameworkPropertyMetadata(double));
public double ExecutionTimeAverage {
get { return (double)GetValue(ExecutionTimeAverageProperty); }
set { SetValue(ExecutionTimeAverageProperty, value); }
}
}
public partial class MainWindow : Window {
public static readonly DependencyProperty ThreadsAvailableCountProperty = DependencyProperty.Register("ThreadsAvailableCount", typeof(int),
typeof(MainWindow), new FrameworkPropertyMetadata(int));
public int ThreadsAvailableCount {
get { return (int)GetValue(ThreadsAvailableCountProperty); }
set { SetValue(ThreadsAvailableCountProperty, value); }
}
}
两个 DependencyProperties
都设置正确并且它们的值显示在 GUI 中。我在这里想念什么?
编辑:
我还测试了以下内容:
<Window>
<!-- This one works fine-->
<TextBlock Width="10" Height="10" VerticalAlignment="Center" Background="{Binding ThreadsAvailableCount, Converter={StaticResource AvgExecutionTimeConverter}, ElementName=Main}"/>
<!-- This one does not work-->
<TextBlock Width="10" Height="10" VerticalAlignment="Center" Background="{Binding ThreadsAvailableCount, Converter={StaticResource ThreadsAvailableCntConverter}, ElementName=Main}"/>
</Window>
似乎Binding
消耗"new"转换器的return值有问题,但我不知道为什么。
EDIT2
我用 Snoop 检查绑定,结果如下:
工作转换器绑定的 background
属性 如下所示:
但是不工作的转换器绑定的 background
属性 看起来是这样的:
ThreadsAvailableCount
设置正确的另一个证明(绑定到 Textblock
):
显示ThreadsAvailableCountToColorConverter
的return值越来越像错误了。这是因为在 Debug 模式下,它会在 ThreadsAvailableCountToColorConverter
的 Convert
方法中的断点处停止。它甚至在 Convert
方法中成功到达 return
。
我认为可能存在多个问题,请查看 'output window' 以了解绑定表达式错误。
1) 确保文本框呈现在不同的区域,而不是
重叠。
2)使用相对路径获取控件,在绑定表达式
中使用属性
你的转换器看起来不错。
以下是我的xaml
<Window x:Class="WhosebugBinding.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:WhosebugBinding="clr-namespace:WhosebugBinding"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<WhosebugBinding:ThreadsAvailableCountToColorConverter x:Key="ThreadsAvailableCntConverter"/>
<WhosebugBinding:AverageExecutionTimeToColorConverter x:Key="AvgExecutionTimeConverter"/>
</Window.Resources>
<Grid>
<!--<DatePicker
x:Name="newtally"
Text="{Binding CustomerLastTally,Mode=TwoWay}"
Margin="0 0 0 0"
/>-->
<!-- This one works fine-->
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Width="30" Height="30" Text="Break"/>
<TextBlock Grid.Row="1" Grid.Column="0" Width="30" Height="30" VerticalAlignment="Center" Text="Break" Background="{Binding ExecutionTimeAverage, Converter={StaticResource AvgExecutionTimeConverter}, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"/>
<!-- This one does not work-->
<TextBlock Grid.Row="2" Grid.Column="0" Width="30" Height="30" VerticalAlignment="Center" Text="Break" Background ="{Binding ThreadsAvailableCount, Converter={StaticResource ThreadsAvailableCntConverter}, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"/>
</Grid>
</Window>
以下是我背后的代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WhosebugBinding
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
// Dependency Property
public static readonly DependencyProperty ExecutionTimeAverageProperty =
DependencyProperty.Register("ExecutionTimeAverage", typeof(DateTime),
typeof(MainWindow), new FrameworkPropertyMetadata(DateTime.Now));
// .NET Property wrapper
public DateTime ExecutionTimeAverage
{
get { return (DateTime)GetValue(ExecutionTimeAverageProperty); }
set { SetValue(ExecutionTimeAverageProperty, value); }
}
// Dependency Property
public static readonly DependencyProperty ThreadsAvailableCountProperty =
DependencyProperty.Register("ThreadsAvailableCount", typeof(int),
typeof(MainWindow), new FrameworkPropertyMetadata(40));
// .NET Property wrapper
public int ThreadsAvailableCount
{
get { return (int)GetValue(ThreadsAvailableCountProperty); }
set { SetValue(ThreadsAvailableCountProperty, value); }
}
}
}
以下是我的转换器
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;
using System.Windows.Media;
namespace WhosebugBinding
{
[ValueConversion(typeof(double), typeof(Brush))]
public class AverageExecutionTimeToColorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
double val;
double.TryParse(value.ToString(), out val);
if (val >= 10000)
{
return Brushes.Red;
}
else if (val >= 5000)
{
return Brushes.Orange;
}
else
{
return Brushes.Green;
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
[ValueConversion(typeof(int), typeof(Brush))]
public class ThreadsAvailableCountToColorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
int val;
int.TryParse(value.ToString(), out val);
if (val < 100)
{
return Brushes.Red;
}
else if (val < 200)
{
return Brushes.Orange;
}
else if (val < 500)
{
return Brushes.Yellow;
}
else
{
return Brushes.Green;
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
啊!终于解决了这个问题。我有同样的问题。使用 TextBlock
,使用 IValueConverter
将 转换为 Brush
.
绑定有效,没有错误或输出。该值进入 IValueConverter
代码,我可以直接调试到 return 语句,然后......什么都没有!
你做的一切都是对的,但是你自动导入了错误的Brushes
。我一直用 WPF 做这件事。
替换 using 语句:
using System.Drawing
与:
using System.Windows.Media
WPF 使用 System.Windows.Media.Brushes
,但 非常 很容易导入几乎相同的 System.Drawing.Brushes
而没有注意到。一切看起来都很好,直到 WPF 掌握它并且不能实际使用它。但是它失败了 'gracefully' 回到默认颜色。
我有一个 Window
class,其中我有几个 TextBlock
元素应该接收 Background
颜色 Binding
属性。第一个 "Converter binding" 工作正常并且完成了预期的一切。今天我尝试用另一个 Converter
实现另一个 "Converter binding",但它不起作用:
(我省略了 ConvertBack
方法,因为它们在这里不是必需的):
namespace InsightTool.Gui.Helper {
[ValueConversion(typeof(double), typeof(Brush))]
public class AverageExecutionTimeToColorConverter : IValueConverter {
public object Convert (object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
double val;
double.TryParse(value.ToString(), out val);
if (val >= 10000) {
return Brushes.Red;
} else if (val >= 5000) {
return Brushes.Orange;
} else {
return Brushes.Green;
}
}
}
[ValueConversion(typeof(int), typeof(Brush))]
public class ThreadsAvailableCountToColorConverter : IValueConverter {
public object Convert (object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
int val;
int.TryParse(value.ToString(), out val);
if (val < 100) {
return Brushes.Red;
} else if (val < 200) {
return Brushes.Orange;
} else if (val < 500) {
return Brushes.Yellow;
} else {
return Brushes.Green;
}
}
}
}
在 Window
class 中,我使用了以下两个转换:
<Window ...
x:Name="Main"
xmlns:Base="clr-namespace:InsightTool.Gui.Helper">
<Window.Resources>
<Base:ThreadsAvailableCountToColorConverter x:Key="ThreadsAvailableCntConverter"/>
<Base:AverageExecutionTimeToColorConverter x:Key="AvgExecutionTimeConverter"/>
</Window.Resources>
<!-- This one works fine-->
<TextBlock Width="10" Height="10" VerticalAlignment="Center" Background="{Binding ExecutionTimeAverage, Converter={StaticResource AvgExecutionTimeConverter}, ElementName=UCExecutionTimes}"/>
<!-- This one does not work-->
<TextBlock Width="10" Height="10" VerticalAlignment="Center" Background="{Binding ThreadsAvailableCount, Converter={StaticResource ThreadsAvailableCntConverter}, ElementName=Main}"/>
</Window>
DependencyProperties
的声明:
public partial class UserControlExecutionTimes : UserControl {
public static readonly DependencyProperty ExecutionTimeAverageProperty =
DependencyProperty.Register("ExecutionTimeAverage", typeof(double), typeof(MainWindow), new FrameworkPropertyMetadata(double));
public double ExecutionTimeAverage {
get { return (double)GetValue(ExecutionTimeAverageProperty); }
set { SetValue(ExecutionTimeAverageProperty, value); }
}
}
public partial class MainWindow : Window {
public static readonly DependencyProperty ThreadsAvailableCountProperty = DependencyProperty.Register("ThreadsAvailableCount", typeof(int),
typeof(MainWindow), new FrameworkPropertyMetadata(int));
public int ThreadsAvailableCount {
get { return (int)GetValue(ThreadsAvailableCountProperty); }
set { SetValue(ThreadsAvailableCountProperty, value); }
}
}
两个 DependencyProperties
都设置正确并且它们的值显示在 GUI 中。我在这里想念什么?
编辑:
我还测试了以下内容:
<Window>
<!-- This one works fine-->
<TextBlock Width="10" Height="10" VerticalAlignment="Center" Background="{Binding ThreadsAvailableCount, Converter={StaticResource AvgExecutionTimeConverter}, ElementName=Main}"/>
<!-- This one does not work-->
<TextBlock Width="10" Height="10" VerticalAlignment="Center" Background="{Binding ThreadsAvailableCount, Converter={StaticResource ThreadsAvailableCntConverter}, ElementName=Main}"/>
</Window>
似乎Binding
消耗"new"转换器的return值有问题,但我不知道为什么。
EDIT2
我用 Snoop 检查绑定,结果如下:
工作转换器绑定的 background
属性 如下所示:
但是不工作的转换器绑定的 background
属性 看起来是这样的:
ThreadsAvailableCount
设置正确的另一个证明(绑定到 Textblock
):
显示ThreadsAvailableCountToColorConverter
的return值越来越像错误了。这是因为在 Debug 模式下,它会在 ThreadsAvailableCountToColorConverter
的 Convert
方法中的断点处停止。它甚至在 Convert
方法中成功到达 return
。
我认为可能存在多个问题,请查看 'output window' 以了解绑定表达式错误。 1) 确保文本框呈现在不同的区域,而不是 重叠。 2)使用相对路径获取控件,在绑定表达式
中使用属性你的转换器看起来不错。
以下是我的xaml
<Window x:Class="WhosebugBinding.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:WhosebugBinding="clr-namespace:WhosebugBinding"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<WhosebugBinding:ThreadsAvailableCountToColorConverter x:Key="ThreadsAvailableCntConverter"/>
<WhosebugBinding:AverageExecutionTimeToColorConverter x:Key="AvgExecutionTimeConverter"/>
</Window.Resources>
<Grid>
<!--<DatePicker
x:Name="newtally"
Text="{Binding CustomerLastTally,Mode=TwoWay}"
Margin="0 0 0 0"
/>-->
<!-- This one works fine-->
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Width="30" Height="30" Text="Break"/>
<TextBlock Grid.Row="1" Grid.Column="0" Width="30" Height="30" VerticalAlignment="Center" Text="Break" Background="{Binding ExecutionTimeAverage, Converter={StaticResource AvgExecutionTimeConverter}, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"/>
<!-- This one does not work-->
<TextBlock Grid.Row="2" Grid.Column="0" Width="30" Height="30" VerticalAlignment="Center" Text="Break" Background ="{Binding ThreadsAvailableCount, Converter={StaticResource ThreadsAvailableCntConverter}, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"/>
</Grid>
</Window>
以下是我背后的代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WhosebugBinding
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
// Dependency Property
public static readonly DependencyProperty ExecutionTimeAverageProperty =
DependencyProperty.Register("ExecutionTimeAverage", typeof(DateTime),
typeof(MainWindow), new FrameworkPropertyMetadata(DateTime.Now));
// .NET Property wrapper
public DateTime ExecutionTimeAverage
{
get { return (DateTime)GetValue(ExecutionTimeAverageProperty); }
set { SetValue(ExecutionTimeAverageProperty, value); }
}
// Dependency Property
public static readonly DependencyProperty ThreadsAvailableCountProperty =
DependencyProperty.Register("ThreadsAvailableCount", typeof(int),
typeof(MainWindow), new FrameworkPropertyMetadata(40));
// .NET Property wrapper
public int ThreadsAvailableCount
{
get { return (int)GetValue(ThreadsAvailableCountProperty); }
set { SetValue(ThreadsAvailableCountProperty, value); }
}
}
}
以下是我的转换器
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;
using System.Windows.Media;
namespace WhosebugBinding
{
[ValueConversion(typeof(double), typeof(Brush))]
public class AverageExecutionTimeToColorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
double val;
double.TryParse(value.ToString(), out val);
if (val >= 10000)
{
return Brushes.Red;
}
else if (val >= 5000)
{
return Brushes.Orange;
}
else
{
return Brushes.Green;
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
[ValueConversion(typeof(int), typeof(Brush))]
public class ThreadsAvailableCountToColorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
int val;
int.TryParse(value.ToString(), out val);
if (val < 100)
{
return Brushes.Red;
}
else if (val < 200)
{
return Brushes.Orange;
}
else if (val < 500)
{
return Brushes.Yellow;
}
else
{
return Brushes.Green;
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
啊!终于解决了这个问题。我有同样的问题。使用 TextBlock
,使用 IValueConverter
将 转换为 Brush
.
绑定有效,没有错误或输出。该值进入 IValueConverter
代码,我可以直接调试到 return 语句,然后......什么都没有!
你做的一切都是对的,但是你自动导入了错误的Brushes
。我一直用 WPF 做这件事。
替换 using 语句:
using System.Drawing
与:
using System.Windows.Media
WPF 使用 System.Windows.Media.Brushes
,但 非常 很容易导入几乎相同的 System.Drawing.Brushes
而没有注意到。一切看起来都很好,直到 WPF 掌握它并且不能实际使用它。但是它失败了 'gracefully' 回到默认颜色。