gpt4 book ai didi

c# - 绑定(bind)到资源 key ,WPF

转载 作者:可可西里 更新时间:2023-11-01 08:16:11 24 4
gpt4 key购买 nike

我有一个包含一些图片的 ResourceDictionary:

<BitmapImage UriSource="..\Images\Bright\folder-bright.png"
x:Key="FolderItemImage" />

我已经为 TreeView 项目创建了一个 HierarchicalTemplate,如下所示:

<HierarchicalDataTemplate ItemsSource="{Binding VisibleChildren}"
DataType="{x:Type st:StructureTreeItem}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding ImageResourceKey}" />
<Image x:Name="iIcon2" Source="{DynamicResource FolderItemImage}"/>
<Image x:Name="iIcon"
Source="{DynamicResource {Binding ImageResourceKey}}"/>
</StackPanel>
</HierarchicalDataTemplate>

现在,当项目显示时:

  • 文本 block 显示 FolderItemImage
  • 显示第一张图片
  • 第二张图片未显示。

整个想法是将项目图像设置为存储在资源中的图像,但不幸的是,上面介绍的技术不起作用,现在我知道原因了:

<Image x:Name="iIcon3" Width="16" Height="16" Margin="0, 1, 3, 1" >
<Image.Source>
<DynamicResource ResourceKey="{Binding ImageResourceKey}" />
</Image.Source>
</Image>

结果:

An unhandled exception of type 'System.Windows.Markup.XamlParseException' occurred in PresentationFramework.dll

Additional information: A 'Binding' cannot be set on the 'ResourceKey' property of type 'DynamicResourceExtension'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject.

所以我必须重新表述我的问题:如何将存储在模型中的一些数据(也许是资源键?)转换为动态资源?它必须是一个动态资源,因为我确定它可能会在运行时发生变化。

最佳答案

我编写了以下标记扩展以允许在一般情况下绑定(bind)到 resourceKey

using System;
using System.ComponentModel;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
using System.Windows.Markup;

namespace Mersoft.Mvvm.MarkupExtensions
{

public class ResourceBinding : MarkupExtension
{
#region Helper properties

public static object GetResourceBindingKeyHelper(DependencyObject obj)
{
return (object)obj.GetValue(ResourceBindingKeyHelperProperty);
}

public static void SetResourceBindingKeyHelper(DependencyObject obj, object value)
{
obj.SetValue(ResourceBindingKeyHelperProperty, value);
}

// Using a DependencyProperty as the backing store for ResourceBindingKeyHelper. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ResourceBindingKeyHelperProperty =
DependencyProperty.RegisterAttached("ResourceBindingKeyHelper", typeof(object), typeof(ResourceBinding), new PropertyMetadata(null, ResourceKeyChanged));

static void ResourceKeyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var target = d as FrameworkElement;
var newVal = e.NewValue as Tuple<object, DependencyProperty>;

if (target == null || newVal == null)
return;

var dp = newVal.Item2;

if (newVal.Item1 == null)
{
target.SetValue(dp, dp.GetMetadata(target).DefaultValue);
return;
}

target.SetResourceReference(dp, newVal.Item1);

}

#endregion

public ResourceBinding()
{

}

public ResourceBinding(string path)
{
this.Path = new PropertyPath(path);
}

public override object ProvideValue(IServiceProvider serviceProvider)
{
var provideValueTargetService = (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget));
if (provideValueTargetService == null)
return null;

if (provideValueTargetService.TargetObject != null &&
provideValueTargetService.TargetObject.GetType().FullName == "System.Windows.SharedDp")
return this;


var targetObject = provideValueTargetService.TargetObject as FrameworkElement;
var targetProperty = provideValueTargetService.TargetProperty as DependencyProperty;
if (targetObject == null || targetProperty == null)
return null;



var binding = new Binding();

#region binding

binding.Path = this.Path;
binding.XPath = this.XPath;
binding.Mode = this.Mode;
binding.UpdateSourceTrigger = this.UpdateSourceTrigger;
binding.Converter = this.Converter;
binding.ConverterParameter = this.ConverterParameter;
binding.ConverterCulture = this.ConverterCulture;

if (this.RelativeSource != null)
binding.RelativeSource = this.RelativeSource;

if (this.ElementName != null)
binding.ElementName = this.ElementName;

if (this.Source != null)
binding.Source = this.Source;

binding.FallbackValue = this.FallbackValue;

#endregion

var multiBinding = new MultiBinding();
multiBinding.Converter = HelperConverter.Current;
multiBinding.ConverterParameter = targetProperty;

multiBinding.Bindings.Add(binding);

multiBinding.NotifyOnSourceUpdated = true;

targetObject.SetBinding(ResourceBindingKeyHelperProperty, multiBinding);

return null;

}


#region Binding Members

/// <summary> The source path (for CLR bindings).</summary>
public object Source
{
get;
set;
}

/// <summary> The source path (for CLR bindings).</summary>
public PropertyPath Path
{
get;
set;
}

/// <summary> The XPath path (for XML bindings).</summary>
[DefaultValue(null)]
public string XPath
{
get;
set;
}

/// <summary> Binding mode </summary>
[DefaultValue(BindingMode.Default)]
public BindingMode Mode
{
get;
set;
}

/// <summary> Update type </summary>
[DefaultValue(UpdateSourceTrigger.Default)]
public UpdateSourceTrigger UpdateSourceTrigger
{
get;
set;
}

/// <summary> The Converter to apply </summary>
[DefaultValue(null)]
public IValueConverter Converter
{
get;
set;
}

/// <summary>
/// The parameter to pass to converter.
/// </summary>
/// <value></value>
[DefaultValue(null)]
public object ConverterParameter
{
get;
set;
}

/// <summary> Culture in which to evaluate the converter </summary>
[DefaultValue(null)]
[TypeConverter(typeof(System.Windows.CultureInfoIetfLanguageTagConverter))]
public CultureInfo ConverterCulture
{
get;
set;
}

/// <summary>
/// Description of the object to use as the source, relative to the target element.
/// </summary>
[DefaultValue(null)]
public RelativeSource RelativeSource
{
get;
set;
}

/// <summary> Name of the element to use as the source </summary>
[DefaultValue(null)]
public string ElementName
{
get;
set;
}


#endregion

#region BindingBase Members

/// <summary> Value to use when source cannot provide a value </summary>
/// <remarks>
/// Initialized to DependencyProperty.UnsetValue; if FallbackValue is not set, BindingExpression
/// will return target property's default when Binding cannot get a real value.
/// </remarks>
public object FallbackValue
{
get;
set;
}

#endregion



#region Nested types

private class HelperConverter : IMultiValueConverter
{
public static readonly HelperConverter Current = new HelperConverter();

public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
return Tuple.Create(values[0], (DependencyProperty)parameter);
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}

#endregion
}
}

用法

<Image Source="{local:ResourceBinding ImageResourceKey}"/>

关于c# - 绑定(bind)到资源 key ,WPF,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20564862/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com