WPF 样式的绑定
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/410579/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Binding for WPF Styles
提问by Matthew Savage
I'm trying to create a custom control - a button - which will have multiple styles applied to it depending on the value of a property within the data context.
我正在尝试创建一个自定义控件 - 一个按钮 - 它将根据数据上下文中的属性值应用多种样式。
What I was thinking is using something similar to:
我在想的是使用类似的东西:
<Button Style="{Binding Path=ButtonStyleProperty, Converter={StaticResource styleConverter}}" Text="{Binding Path=TextProp}" />
And in code... Implement an IValueConverter which does something similar to the code below in the ConvertTo
method:
在代码中...实现一个 IValueConverter,它在ConvertTo
方法中执行类似于以下代码的操作:
switch(value as ValueEnums)
{
case ValueEnums.Enum1:
FindResource("Enum1ButtonStyle") as Style;
break;
... and so on.
}
However I'm not entirely sure about how to pull out the style object and even if this is possible at all...
但是我不完全确定如何拉出样式对象,即使这是可能的......
What I am doing in the mean time is handling the DataContextChanged
event, then attaching a handler to the PropertyChanged
event of the object being bound to the button - then running the switch statement in there.
与此同时,我正在做的是处理DataContextChanged
事件,然后将一个处理程序附加到PropertyChanged
绑定到按钮的对象的事件上——然后在那里运行 switch 语句。
Its not quite perfect but until I can find a better solution it seems like that is what I'll have to use.
它不是很完美,但在我找到更好的解决方案之前,这似乎是我必须使用的。
回答by Steven Robbins
If you want to replace the whole style (rather than just elements of it) then you'll probably be storing those styles in resources. You should be able to do something along the lines of:
如果您想替换整个样式(而不仅仅是它的元素),那么您可能会将这些样式存储在资源中。您应该能够执行以下操作:
<Button>
<Button.Style>
<MultiBinding Converter="{StaticResource StyleConverter}">
<MultiBinding.Bindings>
<Binding RelativeSource="{RelativeSource Self}"/>
<Binding Path="MyStyleString"/>
</MultiBinding.Bindings>
</MultiBinding>
</Button.Style>
</Button>
By using a MultiBinding and using Self as the first binding we can then lookup resources in our converter. The converter needs to implement IMultiValueConverter (rather than IValueConverter) and can look something like this:
通过使用 MultiBinding 并使用 Self 作为第一个绑定,我们可以在转换器中查找资源。转换器需要实现 IMultiValueConverter(而不是 IValueConverter)并且看起来像这样:
class StyleConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
FrameworkElement targetElement = values[0] as FrameworkElement;
string styleName = values[1] as string;
if (styleName == null)
return null;
Style newStyle = (Style)targetElement.TryFindResource(styleName);
if (newStyle == null)
newStyle = (Style)targetElement.TryFindResource("MyDefaultStyleName");
return newStyle;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
It's not something I do very often, but that should work from memory :)
这不是我经常做的事情,但应该从记忆中工作:)
回答by aku
It seems that you need to use DataTriggerclass. It allows you to apply different styles to your button based on it's content.
看来您需要使用DataTrigger类。它允许您根据按钮的内容将不同的样式应用于按钮。
For example following style will change button's background property to red based on value of data context object's property
例如,以下样式将根据数据上下文对象的属性值将按钮的背景属性更改为红色
<Style x:Key="ButtonStyle" TargetType="{x:Type Button}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path="Some property"}"
Value="some property value">
<Setter Property="Background" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
回答by si618
For those of us who can't use multi value converter (I'm looking at you SL4 and WP7:), thanks to Steven's answer I found a way using an ordinary value converter.
对于我们这些不能使用多值转换器的人(我在看你 SL4 和 WP7 :),感谢 Steven 的回答,我找到了一种使用普通值转换器的方法。
The only assumption is the style value is contained within the property of the style being set.
唯一的假设是样式值包含在正在设置的样式的属性中。
So if you're using the MVVM pattern then the style value (such as TextSmall, TextMedium, TextLarge) is assumed to be part of the view model, and all you have to do is pass the converter parameter defining the name of style.
因此,如果您使用的是 MVVM 模式,则假定样式值(例如 TextSmall、TextMedium、TextLarge)是视图模型的一部分,您所要做的就是传递定义样式名称的转换器参数。
For example, say your view model has property:
例如,假设您的视图模型具有属性:
public string ProjectNameStyle
{
get { return string.Format("ProjectNameStyle{0}", _displaySize.ToString()); }
}
Application style:
申请风格:
<Application.Resources>
<Style x:Key="ProjectNameStyleSmall" TargetType="TextBlock">
<Setter Property="FontSize" Value="40" />
</Style>
<Style x:Key="ProjectNameStyleMedium" TargetType="TextBlock">
<Setter Property="FontSize" Value="64" />
</Style>
<Style x:Key="ProjectNameStyleLarge" TargetType="TextBlock">
<Setter Property="FontSize" Value="90" />
</Style>
XAML view:
XAML 视图:
<TextBlock
Text="{Binding Name}"
Style="{Binding ., Mode=OneWay, Converter={cv:StyleConverter}, ConverterParameter=ProjectNameStyle}">
With your StyleConverter class implementing IValueConverter:
使用 StyleConverter 类实现 IValueConverter:
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (targetType != typeof(Style))
{
throw new InvalidOperationException("The target must be a Style");
}
var styleProperty = parameter as string;
if (value == null || styleProperty == null)
{
return null;
}
string styleValue = value.GetType()
.GetProperty(styleProperty)
.GetValue(value, null)
.ToString();
if (styleValue == null)
{
return null;
}
Style newStyle = (Style)Application.Current.TryFindResource(styleValue);
return newStyle;
}
Note that this is WPF code, as the converter is derived from a MarkupExtension as well as IValueConverter, but it will work in SL4 and WP7 if you use static resource and add a bit more leg work as the TryFindResource method doesn't exist.
请注意,这是 WPF 代码,因为转换器是从 MarkupExtension 和 IValueConverter 派生的,但如果您使用静态资源并添加更多的工作,因为 TryFindResource 方法不存在,它将在 SL4 和 WP7 中工作。
Hope that helps someone, and thanks again Steven!
希望对某人有所帮助,再次感谢史蒂文!
回答by Chandru A
ViewModel
视图模型
private Style _dynamicStyle = (Style)Application.Current.FindResource("Style1");
public Style DynamicStyle
{
get { return _dynamicStyle; }
set
{
_dynamicStyle = value;
OnPropertyChanged("DynamicStyle");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
Implement a property in your ViewModel and then dynamically change style where ever you want like below.
在您的 ViewModel 中实现一个属性,然后在您想要的任何位置动态更改样式,如下所示。
DynamicStyle=(Style)Application.Current.FindResource("Style2");// you can place this code where the action get fired
View
看法
Then set DataContextvalue and then implement the following code in your view
然后设置DataContext值,然后在您的视图中实现以下代码
<Button Style="{Binding DynamicStyle,Mode=TwoWay}"/>