在绑定转换器中使用资源作为转换结果
当我尝试将值转换器从定义的枚举状态绑定到画笔时,我在 XAML 设计器中收到错误:
未找到“OKStatus”资源。
该应用程序运行时运行良好,但我无法在设计器中看到我的 GUI。 我的资源在 color.xaml 文件中定义,该文件在运行时读取。 所有代码都在同一个命名空间内
我的 XAML:
xmlns:config =“clr-namespace: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>
和
状态
我的转换器:
[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;
}
}
在这段代码中,frameElem 不会了解我定义的资源,所以我需要一种方法来访问我的资源设计期间。 这可能吗?
When I try to bind a valueconverter from a defined enum Status to brush, I get an error in my XAML designer:
'OKStatus' resource not found.
The application works fine runtime, but I'm not able to see my GUI in the designer.
My resources are defined in the color.xaml file, which is read at run time.
All code is within the same namespace
My XAML:
xmlns:config="clr-namespace: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>
and
Status
My converter:
[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;
}
}
In this code the frameElem wont have any knowledge of the resources I have defined I guess, so I need a way to get access to my resources during design.
Is this possible?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
是的,有可能,而且你的猜测是正确的。资源查找从逻辑树开始,创建新的
FrameworkElement()
并不能满足这一点。它完全断开了。您可以做的(如果 N8 的建议不起作用,您可能必须做的)是向您的转换器提供对
UserControl
的引用,作为要调用的FrameworkElement
FindResource()
上。N8 的建议可能行不通的原因是
Application.Current.FindResource()
可能从应用程序级资源开始,然后转到系统资源,但您要查找的资源位于 < code>UserControl 的资源。如果它们被放置在 App.xaml 的资源中,它就会起作用。但是,我认为Application.Current
在设计时可能为null
。我能想到的最简单的方法是在
UserControl
的构造函数中:我很确定它在
InitializeComponent()
之前,而不是之后。在 XAML 中执行此操作会更加复杂,因为您可能必须向转换器添加
DependencyProperty
以便将UserControl
绑定到它。我认为这太过分了。另一种方法是将
TrueBrush
和FalseBrush
属性放在转换器上,并在 XAML 中分配它们,这就是我倾向于做的事情,以便我的转换器模糊且通用。 (注意:名称略有不同。)Yes, it is possible, and your guess is correct. Resource finding starts with the logical tree, and creating a new
FrameworkElement()
doesn't satisfy this. It's completely disconnected.What you can do (and what you may have to do if N8's suggestion doesn't work), is to hand your converter a reference to the
UserControl
as theFrameworkElement
to callFindResource()
on.The reason N8's suggestion probably won't work is that
Application.Current.FindResource()
probably starts at application-level resources and then goes to system resources, but the resources you're after are in theUserControl
's resources. If they were placed in App.xaml's resources, it would work. However, I thinkApplication.Current
may benull
at design-time.The easiest way I can think of to do this is in your
UserControl
's constructor:I'm pretty sure it goes before
InitializeComponent()
, rather than after.Doing this in XAML would be more complicated, as you probably have to add a
DependencyProperty
to your converter so that you could bind theUserControl
to it. I think that would be going overboard.Another way is to put
TrueBrush
andFalseBrush
properties on your converter and assign them in XAML, which is what I tend to do so that my converters are vague and general-use. (NB: Names are slightly different.)我认为问题在于您试图从框架元素而不是可视化树中查找资源。您可以尝试以下方法吗?
I think the issue is that you are trying to find the resource out of a framework element not in the visual tree. Could you try the following instead?
据我从 TechNet Wiki 了解到,有必要使用 MultiValue Converter 和 MultiValueBinding 来通过 UserControl 获取正确的注册转换器和正确的 FrameworkElement。
XAML示例:
那么转换器声明可以看:
详细解释是:
https://social.technet.microsoft.com/wiki/contents/articles/12423.wpfhowto-pass-and-use-a-control-in-it-s-own- valueconverter-for-convertconvertback.aspx
As I have learned by TechNet Wiki, there is necessary to use MultiValue Converter and MultiValueBinding to get correct registred converter and correct FrameworkElement by the UserControl.
XAML Example:
Then the converter declaration can looks :
The detail explanation is:
https://social.technet.microsoft.com/wiki/contents/articles/12423.wpfhowto-pass-and-use-a-control-in-it-s-own-valueconverter-for-convertconvertback.aspx
我也遇到了这个问题。我认为调用
Application.Current
是从IValueConverter
获取资源的最佳方式,因为它们不是在每个窗口、页面或控件级别上定义的。如上所述,这需要资源至少是应用程序级别的。但是,由于
Application.Current
引用在设计器中设置为 null,因此此方法始终会破坏设计器。您似乎所做的事情是为设计器提供了一些显示内容,同时您也为正在运行的应用程序提供了对转换器中资源的访问权限。对于所有遇到这个问题的人来说,你们不需要实施刘易斯实施的 Kludge;仅当您希望加载设计器表面时才这样做。它不会影响您的应用程序运行时,因为
Application.Current
调用有一些事情要做。I have run into this problem as well. I think that calling
Application.Current
is the best way to get at resources from anIValueConverter
, since they are not defined on a per window, or page or control, level. This would require the resources to be at least application-level, as stated above.However, since the
Application.Current
reference is set to null in the designer, this method will always break the designer. What you appear to have done is given something for the designer to display, while you have given your running application access to resources in the converter.For all of you out there with this issue, you don't need to implement the Kludge that lewi implemented; this is only if you want the designer surface to load. It does not affect your application while running as the
Application.Current
call has something to do.实际上,我最终所做的(目前)是将 FindResource 更改为 TryFindResource,并将语句放在 try/catch 块中。
到目前为止这似乎有效。
Actually what I ended up doing (for now) was to change from FindResource to TryFindResource, and put the statements in a try/catch block.
This seems to work so far.