在 C# XAML for Windows 8.1 中,如何将样式绑定到变量?
In C# XAML for Windows 8.1 how do I bind styles to a variable?
我已经为这个问题苦苦思索了很长一段时间,所以我想我应该在这里问一下,看看是否有人可以帮助我。首先,我是 C#、XAML 和 Windows 8 编程的新手。
我想做的基本事情是:基于对数据模型的更改(我在 Button_Click 处理程序中的小测试平台项目中正在做的),我想更改<Style>
中的前景值。我已经成功地更改了 <TextBlock>
中的前景值,但在另一个 <TextBlock>
.
上运行的 <Style>
上却没有成功
这是我所做的(请原谅我的冗长,希望它有意义):
我有一个名为 MyColorDataSource 的 class,我将其用作 MyPage.xaml 页面中的绑定目标。这是 class:
中的相关代码
public class MyColorDataSource
{
private MyColors _brush1;
public MyColors Brush1
{
get { return _brush1; }
set { _brush1 = value; }
}
private MyColors _brush2;
public MyColors Brush2
{
get { return _brush2; }
set { _brush2 = value; }
}
public MyColorDataSource()
{
_brush1 = new MyColors();
_brush2 = new MyColors();
_brush1.BrushColor= new SolidColorBrush(Colors.DarkRed);
_brush2.BrushColor = new SolidColorBrush(Colors.Pink);
}
}
您会注意到 MyColorDataSource 中的变量属于 MyColors 类型。这是 class:
的定义
public class MyColors : INotifyPropertyChanged
{
private SolidColorBrush _brushColor;
public SolidColorBrush BrushColor
{
get { return _brushColor; }
set {
if (value != _brushColor)
{
_brushColor = value;
NotifyPropertyChanged("BrushColor");
}
}
}
#region INotifyPropertyChanged Members
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
Debug.WriteLine("in NotifyPropertyChanged for " + propertyName);
}
}
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
这是我写的 XAML,有两个 <TextBlock>
元素,其中一个的前景 属性 直接绑定到数据源,其中一个使用 <Style>
我正在尝试将其绑定到数据源。在 MyPage.xaml:
<Page.Resources>
<Style TargetType="TextBlock" x:Key="BoundColor">
<Setter Property="Foreground" Value="{Binding Brush2.BrushColor}" />
</Style>
</Page.Resources>
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<TextBlock x:Name="TextBlockToFormatWithBinding" Text="Direct Binding" Foreground="{Binding BrushColor}" />
<TextBlock x:Name="TextBlockToFormatWithStyleBinding" Text="Binding through style" Style="{StaticResource BoundColor}"/>
</StackPanel>
我已经在 App.xaml.cs:
中设置了我的 DataSource 变量
public sealed partial class App : Application
{
public static MyColorDataSource ColorDataSource;
public App()
{
this.InitializeComponent();
this.Suspending += this.OnSuspending;
ColorDataSource = new MyColorDataSource();
}
}
然后我访问 MyPage.xaml.cs:
中的数据源
public MyPage()
{
this.InitializeComponent();
App.ColorDataSource.Brush1.BrushColor = new SolidColorBrush(Colors.DarkOliveGreen);
App.ColorDataSource.Brush2.BrushColor = new SolidColorBrush(Colors.DarkKhaki);
this.DataContext = App.ColorDataSource;
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
TextBlockToFormatWithBinding.DataContext = App.ColorDataSource.Brush1;
// TextBlockToFormatWithStyleBinding.DataContext = App.ColorDataSource.Brush2; // tried this, it did nothing
}
如果你还在我身边,谢谢你!发生的情况是第一个 <TextBlock>
按预期显示为暗橄榄绿。第二个 <TextBlock>
根本没有出现,我假设它的前景默认为黑色(页面背景也是黑色,所以我看不到)。当我将 <Style>
中的前景值更改为 "DarkRed" 之类的值时,瞧,它会按预期显示。所以 <TextBlock>
肯定存在,但它并没有像我希望的那样从 DataModel 获取前景值。
有没有人 运行 以前遇到过这个问题,如果有,您是如何解决的?我真的不想单独更改每个 <TextBlock>
,因为我打算尝试为 <ListView>
中的项目设置样式,而且我真的不想遍历所有 [=33] =]s 并一一更改其样式。在完成了很多 HTML/CSS/jQuery 之后,我习惯于通过 class 来设置样式,而不是一次一个地迭代。
在此先感谢您提供的任何帮助或建议。
编辑:
我确实设法 运行 通过一种技术,使我非常接近我在这里尝试做的事情,部分是在下面的答案的帮助下(再次感谢!)。希望如果其他人提出类似的问题,这会有所帮助。
<SolidColorBrush x:Key="myBrush" Color="#330000FF" />
<Style TargetType="TextBlock" x:Key="BoundColor">
<Setter Property="Foreground" Value="{StaticResource myBrush}" />
</Style>
然后在我的代码隐藏中,我可以做这样的事情:
((SolidColorBrush)Resources["myBrush"]).Color = Color.FromArgb(64, 255, 0, 0);
这本身并没有将元素的颜色放入数据模型中,但老实说,元素的颜色真的属于数据模型吗?我通常会说它没有。
请注意,我没有任何运气让这项技术在 'Visibility' <Setter>
上发挥作用,我试图将其应用(我希望 TextBlock 有时隐藏,有时可见),但是对于颜色和其他基于对象的 <Setter>
s 它工作得很好。我的假设基于我所知道的一点点,这是真的,因为 Visibility 是一个枚举,而不是 class。所以虽然我可以把它放在我的 <Page.Resources>
:
<Visibility x:Key="TextBlockVisibility">0</Visibility>
<Style>
中的这个:
<Setter Property="Visibility" Value="{StaticResource TextBlockVisibility}" />
我似乎无法改变 TextBlockVisibility
的值,以至于 <Style>
会注意到值的变化或受其影响。
抱歉,你不能。就像许多非常有用的 WPF 功能一样(您的代码在 WPF 程序中工作得很好),这是 AFAIK Windows Phone.
不支持的
也就是说,您可以解决该问题。最明显的解决方案是首先不使用样式。另一种解决方案是使用 "helper" 对象作为样式中的实际 setter 值,它本身通过样式的 setter 设置的附加 属性 来管理绑定。
可以在 David Anson 的网站上找到此技术的示例,网址为:
The taming of the phone [New SetterValueBindingHelper sample demonstrates its usefulness on Windows Phone 7 (and Silverlight 4)]
使用该示例,您的样式 setter 可能如下所示:
<Setter Property="delay:SetterValueBindingHelper.PropertyBinding">
<Setter.Value>
<delay:SetterValueBindingHelper
Property="Foreground"
Binding="{Binding Brush2.BrushColor}"/>
</Setter.Value>
</Setter>
(注意:我实际上并没有测试您的代码的工作示例;您可能需要 fiddle 绑定本身来获得正确的数据上下文,因为我不确定将正确地从具有额外间接寻址的页面继承上下文。)
我已经为这个问题苦苦思索了很长一段时间,所以我想我应该在这里问一下,看看是否有人可以帮助我。首先,我是 C#、XAML 和 Windows 8 编程的新手。
我想做的基本事情是:基于对数据模型的更改(我在 Button_Click 处理程序中的小测试平台项目中正在做的),我想更改<Style>
中的前景值。我已经成功地更改了 <TextBlock>
中的前景值,但在另一个 <TextBlock>
.
<Style>
上却没有成功
这是我所做的(请原谅我的冗长,希望它有意义):
我有一个名为 MyColorDataSource 的 class,我将其用作 MyPage.xaml 页面中的绑定目标。这是 class:
中的相关代码public class MyColorDataSource
{
private MyColors _brush1;
public MyColors Brush1
{
get { return _brush1; }
set { _brush1 = value; }
}
private MyColors _brush2;
public MyColors Brush2
{
get { return _brush2; }
set { _brush2 = value; }
}
public MyColorDataSource()
{
_brush1 = new MyColors();
_brush2 = new MyColors();
_brush1.BrushColor= new SolidColorBrush(Colors.DarkRed);
_brush2.BrushColor = new SolidColorBrush(Colors.Pink);
}
}
您会注意到 MyColorDataSource 中的变量属于 MyColors 类型。这是 class:
的定义public class MyColors : INotifyPropertyChanged
{
private SolidColorBrush _brushColor;
public SolidColorBrush BrushColor
{
get { return _brushColor; }
set {
if (value != _brushColor)
{
_brushColor = value;
NotifyPropertyChanged("BrushColor");
}
}
}
#region INotifyPropertyChanged Members
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
Debug.WriteLine("in NotifyPropertyChanged for " + propertyName);
}
}
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
这是我写的 XAML,有两个 <TextBlock>
元素,其中一个的前景 属性 直接绑定到数据源,其中一个使用 <Style>
我正在尝试将其绑定到数据源。在 MyPage.xaml:
<Page.Resources>
<Style TargetType="TextBlock" x:Key="BoundColor">
<Setter Property="Foreground" Value="{Binding Brush2.BrushColor}" />
</Style>
</Page.Resources>
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<TextBlock x:Name="TextBlockToFormatWithBinding" Text="Direct Binding" Foreground="{Binding BrushColor}" />
<TextBlock x:Name="TextBlockToFormatWithStyleBinding" Text="Binding through style" Style="{StaticResource BoundColor}"/>
</StackPanel>
我已经在 App.xaml.cs:
中设置了我的 DataSource 变量public sealed partial class App : Application
{
public static MyColorDataSource ColorDataSource;
public App()
{
this.InitializeComponent();
this.Suspending += this.OnSuspending;
ColorDataSource = new MyColorDataSource();
}
}
然后我访问 MyPage.xaml.cs:
中的数据源public MyPage()
{
this.InitializeComponent();
App.ColorDataSource.Brush1.BrushColor = new SolidColorBrush(Colors.DarkOliveGreen);
App.ColorDataSource.Brush2.BrushColor = new SolidColorBrush(Colors.DarkKhaki);
this.DataContext = App.ColorDataSource;
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
TextBlockToFormatWithBinding.DataContext = App.ColorDataSource.Brush1;
// TextBlockToFormatWithStyleBinding.DataContext = App.ColorDataSource.Brush2; // tried this, it did nothing
}
如果你还在我身边,谢谢你!发生的情况是第一个 <TextBlock>
按预期显示为暗橄榄绿。第二个 <TextBlock>
根本没有出现,我假设它的前景默认为黑色(页面背景也是黑色,所以我看不到)。当我将 <Style>
中的前景值更改为 "DarkRed" 之类的值时,瞧,它会按预期显示。所以 <TextBlock>
肯定存在,但它并没有像我希望的那样从 DataModel 获取前景值。
有没有人 运行 以前遇到过这个问题,如果有,您是如何解决的?我真的不想单独更改每个 <TextBlock>
,因为我打算尝试为 <ListView>
中的项目设置样式,而且我真的不想遍历所有 [=33] =]s 并一一更改其样式。在完成了很多 HTML/CSS/jQuery 之后,我习惯于通过 class 来设置样式,而不是一次一个地迭代。
在此先感谢您提供的任何帮助或建议。
编辑:
我确实设法 运行 通过一种技术,使我非常接近我在这里尝试做的事情,部分是在下面的答案的帮助下(再次感谢!)。希望如果其他人提出类似的问题,这会有所帮助。
<SolidColorBrush x:Key="myBrush" Color="#330000FF" />
<Style TargetType="TextBlock" x:Key="BoundColor">
<Setter Property="Foreground" Value="{StaticResource myBrush}" />
</Style>
然后在我的代码隐藏中,我可以做这样的事情:
((SolidColorBrush)Resources["myBrush"]).Color = Color.FromArgb(64, 255, 0, 0);
这本身并没有将元素的颜色放入数据模型中,但老实说,元素的颜色真的属于数据模型吗?我通常会说它没有。
请注意,我没有任何运气让这项技术在 'Visibility' <Setter>
上发挥作用,我试图将其应用(我希望 TextBlock 有时隐藏,有时可见),但是对于颜色和其他基于对象的 <Setter>
s 它工作得很好。我的假设基于我所知道的一点点,这是真的,因为 Visibility 是一个枚举,而不是 class。所以虽然我可以把它放在我的 <Page.Resources>
:
<Visibility x:Key="TextBlockVisibility">0</Visibility>
<Style>
中的这个:
<Setter Property="Visibility" Value="{StaticResource TextBlockVisibility}" />
我似乎无法改变 TextBlockVisibility
的值,以至于 <Style>
会注意到值的变化或受其影响。
抱歉,你不能。就像许多非常有用的 WPF 功能一样(您的代码在 WPF 程序中工作得很好),这是 AFAIK Windows Phone.
不支持的也就是说,您可以解决该问题。最明显的解决方案是首先不使用样式。另一种解决方案是使用 "helper" 对象作为样式中的实际 setter 值,它本身通过样式的 setter 设置的附加 属性 来管理绑定。
可以在 David Anson 的网站上找到此技术的示例,网址为: The taming of the phone [New SetterValueBindingHelper sample demonstrates its usefulness on Windows Phone 7 (and Silverlight 4)]
使用该示例,您的样式 setter 可能如下所示:
<Setter Property="delay:SetterValueBindingHelper.PropertyBinding">
<Setter.Value>
<delay:SetterValueBindingHelper
Property="Foreground"
Binding="{Binding Brush2.BrushColor}"/>
</Setter.Value>
</Setter>
(注意:我实际上并没有测试您的代码的工作示例;您可能需要 fiddle 绑定本身来获得正确的数据上下文,因为我不确定将正确地从具有额外间接寻址的页面继承上下文。)