如何从绑定值设置 Static/Dynamic 资源?
How can I set a Static/Dynamic resource from a binding value?
我想使用包含 TextBlock 控件的数据模板添加动态项目,但 TextBlock 控件的文本将从 XAML ResourceDictionary 中选择。静态资源名称将根据绑定值的结果得到。
我该怎么做?
我正在尝试这样的事情,但不起作用。
<DataTemplate x:Key="languageItemTemplate">
<ContentControl>
<StackPanel>
<TextBlock Text="{StaticResource {Binding ResourceName}}"></TextBlock>
<TextBlock Text="{DynamicResource {Binding ResourceName}}"></TextBlock>
</StackPanel>
</ContentControl>
</DataTemplate>
更新
感谢 Tobias,他的答案的第一个选项有效。但我需要首先实例化转换器才能使其工作。哪一个是最好的主意?
在application_startup方法中并将其用于所有应用程序或在window的Window.Resources中我使用转换器?
也许可以将两者合并并在 Application.Resources 上进行?
感谢您的回答。
private void Application_Startup(object sender, StartupEventArgs e)
{
LoadConverters();
}
private void LoadConverters()
{
foreach (var t in System.Reflection.Assembly.GetExecutingAssembly().GetTypes())
{
if (t.GetInterfaces().Any(i => i.Name == "IValueConverter"))
{
Resources.Add(t.Name, Activator.CreateInstance(t));
}
}
}
或
<local:BindingResourceConverter x:Key="ResourceConverter"/>
<DataTemplate x:Key="languageItemTemplate">
<ContentControl>
<StackPanel>
<TextBlock Text="{Binding Name, Converter={StaticResource ResourceConverter }}" />
</StackPanel>
</ContentControl>
</DataTemplate>
如果资源是应用程序级资源,您可以简单地使用转换器将资源名称转换为实际对象,如下所示:
public class BindingResourceConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
string resourceKey = value as string;
if (!String.IsNullOrEmpty(resourceKey))
{
var resource = Application.Current.FindResource(resourceKey);
if (resource != null)
{
return resource;
}
}
return Binding.DoNothing;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
并像这样使用它:
<TextBlock Text="{Binding ResourceKey, Converter={StaticResource ResourceConverter}}" />
如果资源在局部范围,我们需要对控件的引用来搜索它的资源。您可以使用附加的 属性:
获取资源名称和控件
public class TextBlockHelper
{
public static readonly DependencyProperty TextResourceKeyProperty =
DependencyProperty.RegisterAttached("TextResourceKey", typeof(string),
typeof(TextBlockHelper), new PropertyMetadata(String.Empty, OnTextResourceKeyChanged));
public static string GetTextResourceKey(DependencyObject obj)
{
return (string)obj.GetValue(TextResourceKeyProperty);
}
public static void SetTextResourceKey(DependencyObject obj, string value)
{
obj.SetValue(TextResourceKeyProperty, value);
}
private static void OnTextResourceKeyChanged(
DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
string resourceKey = e.NewValue as string;
if(d is TextBlock tb)
{
var r = tb.TryFindResource(resourceKey);
if (r != null)
{
tb.Text = r.ToString();
}
}
}
}
你可以这样使用它:
<Grid>
<Grid.Resources>
<sys:String x:Key="SomeLocalResource">LocalResource</sys:String>
</Grid.Resources>
<TextBlock h:TextBlockHelper.TextResourceKey="{Binding ResourceKey}" />
</Grid>
我想使用包含 TextBlock 控件的数据模板添加动态项目,但 TextBlock 控件的文本将从 XAML ResourceDictionary 中选择。静态资源名称将根据绑定值的结果得到。
我该怎么做? 我正在尝试这样的事情,但不起作用。
<DataTemplate x:Key="languageItemTemplate">
<ContentControl>
<StackPanel>
<TextBlock Text="{StaticResource {Binding ResourceName}}"></TextBlock>
<TextBlock Text="{DynamicResource {Binding ResourceName}}"></TextBlock>
</StackPanel>
</ContentControl>
</DataTemplate>
更新 感谢 Tobias,他的答案的第一个选项有效。但我需要首先实例化转换器才能使其工作。哪一个是最好的主意?
在application_startup方法中并将其用于所有应用程序或在window的Window.Resources中我使用转换器?
也许可以将两者合并并在 Application.Resources 上进行?
感谢您的回答。
private void Application_Startup(object sender, StartupEventArgs e)
{
LoadConverters();
}
private void LoadConverters()
{
foreach (var t in System.Reflection.Assembly.GetExecutingAssembly().GetTypes())
{
if (t.GetInterfaces().Any(i => i.Name == "IValueConverter"))
{
Resources.Add(t.Name, Activator.CreateInstance(t));
}
}
}
或
<local:BindingResourceConverter x:Key="ResourceConverter"/>
<DataTemplate x:Key="languageItemTemplate">
<ContentControl>
<StackPanel>
<TextBlock Text="{Binding Name, Converter={StaticResource ResourceConverter }}" />
</StackPanel>
</ContentControl>
</DataTemplate>
如果资源是应用程序级资源,您可以简单地使用转换器将资源名称转换为实际对象,如下所示:
public class BindingResourceConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
string resourceKey = value as string;
if (!String.IsNullOrEmpty(resourceKey))
{
var resource = Application.Current.FindResource(resourceKey);
if (resource != null)
{
return resource;
}
}
return Binding.DoNothing;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
并像这样使用它:
<TextBlock Text="{Binding ResourceKey, Converter={StaticResource ResourceConverter}}" />
如果资源在局部范围,我们需要对控件的引用来搜索它的资源。您可以使用附加的 属性:
获取资源名称和控件public class TextBlockHelper
{
public static readonly DependencyProperty TextResourceKeyProperty =
DependencyProperty.RegisterAttached("TextResourceKey", typeof(string),
typeof(TextBlockHelper), new PropertyMetadata(String.Empty, OnTextResourceKeyChanged));
public static string GetTextResourceKey(DependencyObject obj)
{
return (string)obj.GetValue(TextResourceKeyProperty);
}
public static void SetTextResourceKey(DependencyObject obj, string value)
{
obj.SetValue(TextResourceKeyProperty, value);
}
private static void OnTextResourceKeyChanged(
DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
string resourceKey = e.NewValue as string;
if(d is TextBlock tb)
{
var r = tb.TryFindResource(resourceKey);
if (r != null)
{
tb.Text = r.ToString();
}
}
}
}
你可以这样使用它:
<Grid>
<Grid.Resources>
<sys:String x:Key="SomeLocalResource">LocalResource</sys:String>
</Grid.Resources>
<TextBlock h:TextBlockHelper.TextResourceKey="{Binding ResourceKey}" />
</Grid>