【问题标题】:WPF: ValueConverter (IValueConverter) does not workWPF:ValueConverter(IValueConverter)不起作用
【发布时间】:2016-10-07 13:11:53
【问题描述】:

我有一个Window 类,其中我有几个TextBlock 元素,它们应该通过Binding 属性的值接收Background 颜色。第一个“转换器绑定”工作正常,并完成了预期的一切。今天我尝试用另一个 Converter 实现另一个“转换器绑定”,但它不起作用:

(我省略了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 类中,我使用了两种转换方法,如下所示:

<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 消耗“新”转换器的返回值似乎有问题,但我不知道为什么。

EDIT2

我用 Snoop 检查绑定,结果如下:

工作转换器绑定的background 属性如下所示:

但是不工作的转换器绑定的background 属性看起来是这样的:

另一个证明ThreadsAvailableCount 设置正确(绑定到Textblock):

显示ThreadsAvailableCountToColorConverter的返回值似乎越来越错误。这是因为在调试模式下,它会在ThreadsAvailableCountToColorConverterConvert 方法中的断点处停止。甚至在Convert方法中成功到达return

【问题讨论】:

  • 你有没有试过在 ThreadsAvailableCountToColorConverter 的 Convert 方法中放一个断点,看它是否被调用。
  • @R.Rusev 它正在被调用。我已经试过了,但是这个控件的背景颜色只是保持白色
  • 调试器的输出窗口是否有异常或绑定错误?
  • 第二个 TextBlock 是否可能不在您预期的位置或不在顶部。假设您使用的是网格?
  • 删除ValueConversion attribute看看。

标签: c# wpf xaml binding valueconverter


【解决方案1】:

啊!终于解决了这个问题。我有同样的问题。使用 TextBlock,使用 IValueConverter 转换为 Brush

绑定正常工作,没有错误或输出。值进入IValueConverter 代码,我可以一直调试到返回语句然后......什么都没有!

您所做的一切都是正确的,但您自动导入了错误的Brushes。我一直使用 WPF。

替换 using 语句:

using System.Drawing

与:

using System.Windows.Media

WPF 使用System.Windows.Media.Brushes,但非常很容易导入几乎相同的System.Drawing.Brushes 而不会注意到。一切看起来都很好,直到 WPF 掌握它并且不能实际使用它。但它通过使用默认颜色“优雅地”失败了。

【讨论】:

    【解决方案2】:

    我认为可能是多个问题,请查看“输出窗口”中的绑定表达式错误。 1) 确保文本框呈现在单独的区域中,而不是 重叠。 2) 使用相对路径到达控件并在绑定表达式中使用它的属性

    您的转换器看起来不错。

    以下是我的 xaml

    <Window x:Class="StackOverflowBinding.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:stackOverflowBinding="clr-namespace:StackOverflowBinding"
            Title="MainWindow" Height="350" Width="525">
        <Window.Resources>
            <stackOverflowBinding:ThreadsAvailableCountToColorConverter x:Key="ThreadsAvailableCntConverter"/>
            <stackOverflowBinding: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 StackOverflowBinding
    {
        /// <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 StackOverflowBinding
    {
    
        [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();
            }
        }
    }
    

    【讨论】:

    • 感谢您的回复,但这并不能解决问题。
    • 你能像我一样分享你的文件或项目吗?
    • 什么意思?我想我分享了这个问题的所有必要代码
    猜你喜欢
    • 2015-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多