使用资源作为转换会导致绑定转换器

lew*_*ewi 11 wpf valueconverter staticresource

当我尝试将valueconverter从定义的枚举状态绑定到画笔时,我的XAML设计器中出现错误:

找不到'OKStatus'资源.

该应用程序运行良好的运行时,但我无法在设计器中看到我的GUI.我的资源在color.xaml文件中定义,该文件在运行时读取.所有代码都在同一名称空间内

我的XAML:

的xmlns:配置= "CLR的命名空间:App.MyNamespace"

<UserControl.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="c:\Skins\Colors.xaml" />
            <ResourceDictionary Source="c:\Skins\Common.xaml" />                
        </ResourceDictionary.MergedDictionaries>
        <config:StatusConverter x:Key="StateConverter" />
        <config:BoolConverter x:Key="BoolConverter" />
        <config:BooleanConverter x:Key="BooleanConverter" />
    </ResourceDictionary>
</UserControl.Resources>
Run Code Online (Sandbox Code Playgroud)

状态

我的转换器:

[ValueConversion(typeof(bool), typeof(Brush))]
public class BoolConverter : IValueConverter
{
    public object Convert(object value, Type targetType,
        object parameter, CultureInfo culture)
    {
        bool state = (bool)value;

        FrameworkElement FrameElem = new FrameworkElement();

        if (state == true)
            return (FrameElem.FindResource("OKStatus") as Brush);
        else
            return (FrameElem.FindResource("ErrorStatus") as Brush);
    }

    public object ConvertBack(object value, Type targetType,
        object parameter, CultureInfo culture)
    {
        return null;
    }
}
Run Code Online (Sandbox Code Playgroud)

在这段代码中,frameElem不会对我所定义的资源有任何了解,所以我需要一种方法来在设计期间访问我的资源.这可能吗?

Joe*_*ant 14

是的,这是可能的,你的猜测是正确的.资源查找从逻辑树开始,创建新的FrameworkElement()不满足此要求.它完全断开了.

您可以做什么(以及如果N8的建议不起作用,您可能需要做的事情),就是将您的转换器UserControl作为FrameworkElement调用的参考FindResource().

N8的建议可能不起作用的原因可能Application.Current.FindResource()是从应用程序级资源开始然后转到系统资源,但是你所追求的资源都在UserControl资源中.如果将它们放在App.xaml的资源中,那就可以了.但是,我认为Application.Current可能是null在设计时.

我能想到的最简单的方法是在你UserControl的构造函数中:

public MyUserControl(){
    var boolconv = new BoolConverter(); 
    boolconv.FrameworkElement = this;
    this.Resources.Add( "BoolConverter", boolconv );
    InitializeComponent();
}
Run Code Online (Sandbox Code Playgroud)

我很确定它是在它之前InitializeComponent(),而不是之后.

在XAML中执行此操作会更复杂,因为您可能需要DependencyProperty在转换器中添加一个,以便绑定UserControl到它.我认为那将是过分的.

另一种方法是在转换器上放置TrueBrushFalseBrush属性并在XAML中分配它们,这是我倾向于这样做,以便我的转换器模糊和通用.(注意:名称略有不同.)

<config:BoolToBrushConverter x:Key="Bool2Brush"
                      TrueBrush="{StaticResource OKStatusBrush}"
                      FalseBrush="{StaticResource ErrorStatusBrush}" />
Run Code Online (Sandbox Code Playgroud)


Nat*_*lus 6

我认为问题在于您试图从不在可视化树中的框架元素中找到资源.你能尝试下面这个吗?

Application.Current.FindResource("OKStatus") as Brush;
Run Code Online (Sandbox Code Playgroud)

  • 如果资源位于应用程序级字典或系统资源中,那肯定会起作用。 (2认同)

lew*_*ewi -1

实际上,我最终所做的(目前)是将 FindResource 更改为 TryFindResource,并将语句放在 try/catch 块中。到目前为止这似乎有效。

try
{
    if (state == true)
       return (FrameElem.TryFindResource("OKStatus") as Brush);
    else
       return (FrameElem.TryFindResource("ErrorStatus") as Brush);
}

catch (ResourceReferenceKeyNotFoundException)
{
   return new SolidColorBrush(Colors.LightGray);
}
Run Code Online (Sandbox Code Playgroud)