wpf 绑定到静态属性
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/936304/
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 to static property
提问by Anthony Brien
I'm having a hard time binding a simple static string property to a TextBox.
我很难将一个简单的静态字符串属性绑定到一个 TextBox。
Here's the class with the static property:
这是具有静态属性的类:
public class VersionManager
{
private static string filterString;
public static string FilterString
{
get { return filterString; }
set { filterString = value; }
}
}
In my xaml, I just want to bind this static property to a TextBox:
在我的 xaml 中,我只想将此静态属性绑定到 TextBox:
<TextBox>
<TextBox.Text>
<Binding Source="{x:Static local:VersionManager.FilterString}"/>
</TextBox.Text>
</TextBox>
Everything compiles, but at run time, I get the following exception:
一切都编译,但在运行时,我得到以下异常:
Cannot convert the value in attribute 'Source' to object of type 'System.Windows.Markup.StaticExtension'. Error at object 'System.Windows.Data.Binding' in markup file 'BurnDisk;component/selectversionpagefunction.xaml' Line 57 Position 29.
无法将属性“Source”中的值转换为“System.Windows.Markup.StaticExtension”类型的对象。标记文件“BurnDisk;component/selectversionpagefunction.xaml”第 57 行第 29 行中的对象“System.Windows.Data.Binding”出错。
Any idea what I'm doing wrong?
知道我做错了什么吗?
采纳答案by Thomas Levesque
If the binding needs to be two-way, you must supply a path. There's a trick to do two-way binding on a static property, provided the class is not static : declare a dummy instance of the class in the resources, and use it as the source of the binding.
如果绑定需要双向,则必须提供路径。如果类不是静态的,则有一个对静态属性进行双向绑定的技巧:在资源中声明类的虚拟实例,并将其用作绑定的源。
<Window.Resources>
<local:VersionManager x:Key="versionManager"/>
</Window.Resources>
...
<TextBox Text="{Binding Source={StaticResource versionManager}, Path=FilterString}"/>
回答by Adam Sills
You can't bind to a static like that. There's no way for the binding infrastructure to get notified of updates since there's no DependencyObject
(or object instance that implement INotifyPropertyChanged
) involved.
你不能绑定到这样的静态。绑定基础结构无法获得更新通知,因为不涉及DependencyObject
(或实现的对象实例INotifyPropertyChanged
)。
If that value doesn't change, just ditch the binding and use x:Static
directly inside the Text
property. Define app
below to be the namespace (and assembly) location of the VersionManager class.
如果该值没有改变,只需放弃绑定并x:Static
直接在Text
属性内部使用。app
下面定义为 VersionManager 类的命名空间(和程序集)位置。
<TextBox Text="{x:Static app:VersionManager.FilterString}" />
If the value does change, I'd suggest creating a singleton to contain the value and bind to that.
如果该值确实发生了变化,我建议创建一个单例来包含该值并绑定到该值。
An example of the singleton:
单例的一个例子:
public class VersionManager : DependencyObject {
public static readonly DependencyProperty FilterStringProperty =
DependencyProperty.Register( "FilterString", typeof( string ),
typeof( VersionManager ), new UIPropertyMetadata( "no version!" ) );
public string FilterString {
get { return (string) GetValue( FilterStringProperty ); }
set { SetValue( FilterStringProperty, value ); }
}
public static VersionManager Instance { get; private set; }
static VersionManager() {
Instance = new VersionManager();
}
}
<TextBox Text="{Binding Source={x:Static local:VersionManager.Instance},
Path=FilterString}"/>
回答by Jowen
In .NET 4.5 it's possible to bind to static properties, read more
在 .NET 4.5 中可以绑定到静态属性,阅读更多
You can use static properties as the source of a data binding. The data binding engine recognizes when the property's value changes if a static event is raised. For example, if the class SomeClass defines a static property called MyProperty, SomeClass can define a static event that is raised when the value of MyProperty changes. The static event can use either of the following signatures:
您可以使用静态属性作为数据绑定的来源。如果引发静态事件,数据绑定引擎会识别属性值何时更改。例如,如果类 SomeClass 定义了一个名为 MyProperty 的静态属性,则 SomeClass 可以定义一个静态事件,该事件在 MyProperty 的值更改时引发。静态事件可以使用以下任一签名:
public static event EventHandler MyPropertyChanged;
public static event EventHandler<PropertyChangedEventArgs> StaticPropertyChanged;
Note that in the first case, the class exposes a static event named PropertyNameChanged that passes EventArgs to the event handler. In the second case, the class exposes a static event named StaticPropertyChanged that passes PropertyChangedEventArgs to the event handler. A class that implements the static property can choose to raise property-change notifications using either method.
请注意,在第一种情况下,该类公开了一个名为 PropertyNameChanged 的静态事件,该事件将 EventArgs 传递给事件处理程序。在第二种情况下,该类公开一个名为 StaticPropertyChanged 的静态事件,该事件将 PropertyChangedEventArgs 传递给事件处理程序。实现静态属性的类可以选择使用任一方法引发属性更改通知。
回答by Matt
As of WPF 4.5 you can bind directly to static properties and have the binding automatically update when your property is changed. You do need to manually wire up a change event to trigger the binding updates.
从 WPF 4.5 开始,您可以直接绑定到静态属性,并在属性更改时自动更新绑定。您确实需要手动连接更改事件以触发绑定更新。
public class VersionManager
{
private static String _filterString;
/// <summary>
/// A static property which you'd like to bind to
/// </summary>
public static String FilterString
{
get
{
return _filterString;
}
set
{
_filterString = value;
// Raise a change event
OnFilterStringChanged(EventArgs.Empty);
}
}
// Declare a static event representing changes to your static property
public static event EventHandler FilterStringChanged;
// Raise the change event through this static method
protected static void OnFilterStringChanged(EventArgs e)
{
EventHandler handler = FilterStringChanged;
if (handler != null)
{
handler(null, e);
}
}
static VersionManager()
{
// Set up an empty event handler
FilterStringChanged += (sender, e) => { return; };
}
}
You can now bind your static property just like any other:
您现在可以像绑定其他任何其他属性一样绑定您的静态属性:
<TextBox Text="{Binding Path=(local:VersionManager.FilterString)}"/>
回答by Kylo Ren
There could be two ways/syntax to bind a static
property. If pis a static
property in class MainWindow
, then binding
for textbox
will be:
可能有两种方式/语法来绑定static
属性。如果p是static
class 中的一个属性MainWindow
,那么binding
fortextbox
将是:
1.
1.
<TextBox Text="{x:Static local:MainWindow.p}" />
2.
2.
<TextBox Text="{Binding Source={x:Static local:MainWindow.p},Mode=OneTime}" />
回答by GPAshka
You can use ObjectDataProvider
class and it's MethodName
property. It can look like this:
您可以使用ObjectDataProvider
class 及其MethodName
属性。它看起来像这样:
<Window.Resources>
<ObjectDataProvider x:Key="versionManager" ObjectType="{x:Type VersionManager}" MethodName="get_FilterString"></ObjectDataProvider>
</Window.Resources>
Declared object data provider can be used like this:
声明的对象数据提供者可以这样使用:
<TextBox Text="{Binding Source={StaticResource versionManager}}" />
回答by Edmund Covington
If you are using local resources you can refer to them as below:
如果您使用的是本地资源,您可以参考如下:
<TextBlock Text="{Binding Source={x:Static prop:Resources.PerUnitOfMeasure}}" TextWrapping="Wrap" TextAlignment="Center"/>
回答by Alexei Shcherbakov
Right variant for .NET 4.5 +
.NET 4.5 + 的正确变体
C# code
C# 代码
public class VersionManager
{
private static string filterString;
public static string FilterString
{
get => filterString;
set
{
if (filterString == value)
return;
filterString = value;
StaticPropertyChanged?.Invoke(null, FilterStringPropertyEventArgs);
}
}
private static readonly PropertyChangedEventArgs FilterStringPropertyEventArgs = new PropertyChangedEventArgs (nameof(FilterString));
public static event PropertyChangedEventHandler StaticPropertyChanged;
}
XAML binding (attention to braces they are (), not {})
XAML 绑定(注意大括号是 (),而不是 {})
<TextBox Text="{Binding Path=(yournamespace:VersionManager.FilterString)}" />
回答by Alex141
Look at my project CalcBinding, which provides to you writing complex expressions in Path property value, including static properties, source properties, Math and other. So, you can write this:
看看我的项目CalcBinding,它提供给你在 Path 属性值中编写复杂的表达式,包括静态属性、源属性、Math 等。所以,你可以这样写:
<TextBox Text="{c:Binding local:VersionManager.FilterString}"/>
Goodluck!
祝你好运!
回答by kayleeFrye_onDeck
These answers are all good if you want to follow good conventions but the OP wanted something simple, which is what I wanted too instead of dealing with GUI design patterns. If all you want to do is have a string in a basic GUI app you can update ad-hoc without anything fancy, you can just access it directly in your C# source.
如果您想遵循良好的约定,这些答案都很好,但 OP 想要一些简单的东西,这也是我想要的,而不是处理 GUI 设计模式。如果您想要做的只是在基本 GUI 应用程序中包含一个字符串,您可以不加任何花哨地进行临时更新,您可以直接在 C# 源代码中访问它。
Let's say you've got a really basic WPF app MainWindow XAML like this,
假设您有一个非常基本的 WPF 应用程序 MainWindow XAML,如下所示,
<Window x:Class="MyWPFApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:MyWPFApp"
mc:Ignorable="d"
Title="MainWindow"
Height="200"
Width="400"
Background="White" >
<Grid>
<TextBlock x:Name="textBlock"
Text=".."
HorizontalAlignment="Center"
VerticalAlignment="Top"
FontWeight="Bold"
FontFamily="Helvetica"
FontSize="16"
Foreground="Blue" Margin="0,10,0,0"
/>
<Button x:Name="Find_Kilroy"
Content="Poke Kilroy"
Click="Button_Click_Poke_Kilroy"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontFamily="Helvetica"
FontWeight="Bold"
FontSize="14"
Width="280"
/>
</Grid>
</Window>
That will look something like this:
这看起来像这样:
In your MainWindow XAML's source, you could have something like this where all we're doing in changing the value directly via textBlock.Text
's get
/set
functionality:
在您的 MainWindow XAML 的源代码中,您可能有这样的事情,我们正在通过textBlock.Text
's get
/set
功能直接更改值:
using System.Windows;
namespace MyWPFApp
{
public partial class MainWindow : Window
{
public MainWindow() { InitializeComponent(); }
private void Button_Click_Poke_Kilroy(object sender, RoutedEventArgs e)
{
textBlock.Text = " \|||/\r\n" +
" (o o) \r\n" +
"----ooO- (_) -Ooo----";
}
}
}
Then when you trigger that click event by clicking the button, voila! Kilroy appears :)
然后,当您通过单击按钮触发该单击事件时,瞧!基尔罗伊出现:)