Mat*_*age 34 data-binding wpf styles
我正在尝试创建一个自定义控件 - 一个按钮 - 根据数据上下文中属性的值,它将应用多种样式.
我在想的是使用类似的东西:
<Button Style="{Binding Path=ButtonStyleProperty, Converter={StaticResource styleConverter}}" Text="{Binding Path=TextProp}" />
Run Code Online (Sandbox Code Playgroud)
在代码中......实现一个IValueConverter,它在ConvertTo
方法中执行类似下面的代码:
switch(value as ValueEnums)
{
case ValueEnums.Enum1:
FindResource("Enum1ButtonStyle") as Style;
break;
... and so on.
}
Run Code Online (Sandbox Code Playgroud)
但是我不完全确定如何拉出样式对象,即使这是可能的......
我正在做的事情是处理DataContextChanged
事件,然后将处理程序附加到PropertyChanged
绑定到按钮的对象的事件 - 然后在那里运行switch语句.
它不是很完美,但在我找到一个更好的解决方案之前,我似乎必须使用它.
Ste*_*ins 38
如果你想要替换整个样式(而不仅仅是它的元素)那么你可能会将这些样式存储在资源中.你应该能够做一些事情:
<Button>
<Button.Style>
<MultiBinding Converter="{StaticResource StyleConverter}">
<MultiBinding.Bindings>
<Binding RelativeSource="{RelativeSource Self}"/>
<Binding Path="MyStyleString"/>
</MultiBinding.Bindings>
</MultiBinding>
</Button.Style>
</Button>
Run Code Online (Sandbox Code Playgroud)
通过使用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();
}
}
Run Code Online (Sandbox Code Playgroud)
这不是我经常做的事情,但这应该从记忆中起作用:)
aku*_*aku 15
看来你需要使用DataTrigger类.它允许您根据内容的不同,为按钮应用不同的样式.
例如,以下样式将根据数据上下文对象的属性值将按钮的背景属性更改为红色
<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>
Run Code Online (Sandbox Code Playgroud)
对于我们这些不能使用多值转换器的人(我正在看你SL4和WP7 :),感谢Steven的回答,我找到了一种使用普通值转换器的方法.
唯一的假设是样式值包含在所设置样式的属性中.
因此,如果您正在使用MVVM模式,则假定样式值(例如TextSmall,TextMedium,TextLarge)是视图模型的一部分,您所要做的就是传递定义样式名称的转换器参数.
例如,假设您的视图模型具有以下属性:
public string ProjectNameStyle
{
get { return string.Format("ProjectNameStyle{0}", _displaySize.ToString()); }
}
Run Code Online (Sandbox Code Playgroud)
应用风格:
<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>
Run Code Online (Sandbox Code Playgroud)
XAML视图:
<TextBlock
Text="{Binding Name}"
Style="{Binding ., Mode=OneWay, Converter={cv:StyleConverter}, ConverterParameter=ProjectNameStyle}">
Run Code Online (Sandbox Code Playgroud)
使用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;
}
Run Code Online (Sandbox Code Playgroud)
请注意,这是WPF代码,因为转换器是从MarkupExtension和IValueConverter派生的,但是如果您使用静态资源并且因为TryFindResource方法不存在而添加更多腿部工作,它将在SL4和WP7中工作.
希望能有所帮助,并再次感谢史蒂文!
归档时间: |
|
查看次数: |
50841 次 |
最近记录: |