绑定到静态属性
Posted
技术标签:
【中文标题】绑定到静态属性【英文标题】:Binding to static property 【发布时间】:2010-10-30 11:52:38 【问题描述】:我很难将简单的静态字符串属性绑定到文本框。
这是具有静态属性的类:
public class VersionManager
private static string filterString;
public static string FilterString
get return filterString;
set filterString = value;
在我的 xaml 中,我只想将此静态属性绑定到 TextBox:
<TextBox>
<TextBox.Text>
<Binding Source="x:Static local:VersionManager.FilterString"/>
</TextBox.Text>
</TextBox>
一切都编译,但在运行时,我得到以下异常:
无法转换属性中的值 “来源”到类型的对象 'System.Windows.Markup.StaticExtension'。 对象错误 'System.Windows.Data.Binding' 在 标记文件 'BurnDisk;组件/selectversionpagefunction.xaml' 第 57 行第 29 行。
知道我做错了什么吗?
【问题讨论】:
【参考方案1】:你不能绑定到这样的静态。由于不涉及 DependencyObject
(或实现 INotifyPropertyChanged
的对象实例),因此绑定基础架构无法收到更新通知。
如果该值没有改变,只需放弃绑定并直接在Text
属性内使用x:Static
。将下面的 app
定义为 VersionManager 类的命名空间(和程序集)位置。
<TextBox Text="x:Static app:VersionManager.FilterString" />
如果值确实发生了变化,我建议创建一个单例来包含该值并绑定到该值。
单例示例:
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"/>
【讨论】:
真的吗?我已经能够绑定到与我的示例非常相似的静态 Int32.MaxValue:如果需要双向绑定,则必须提供路径。
如果类不是静态的,则对静态属性进行双向绑定有一个技巧:在资源中声明该类的虚拟实例,并将其用作绑定源。
<Window.Resources>
<local:VersionManager x:Key="versionManager"/>
</Window.Resources>
...
<TextBox Text="Binding Source=StaticResource versionManager, Path=FilterString"/>
【讨论】:
这个答案更适合我的情况,因为我不想将 DependencyObject 引入我的源类。感谢您的提示! 请注意,这将使您的文本框能够将值推回静态属性,但不会在源值更改时更新文本框。 没关系,在这种情况下,我只需要从文本框到源的绑定。如果我希望绑定以另一种方式工作,我知道需要以下方法之一:INotifyPropertyChanged、在 .NET 4.5 中,可以绑定到静态属性 read more
您可以使用静态属性作为数据绑定的来源。这 数据绑定引擎识别属性值何时更改,如果 引发静态事件。例如,如果类 SomeClass 定义了一个 静态属性叫做 MyProperty,SomeClass 可以定义一个静态事件 当 MyProperty 的值更改时引发。静态事件 可以使用以下任一签名:
public static event EventHandler MyPropertyChanged;
public static event EventHandler<PropertyChangedEventArgs> StaticPropertyChanged;
请注意,在第一种情况下,该类公开了一个名为 将 EventArgs 传递给事件处理程序的 PropertyNameChanged。 在第二种情况下,该类公开了一个名为 StaticPropertyChanged 将 PropertyChangedEventArgs 传递给 事件处理程序。实现静态属性的类可以选择 使用任一方法引发属性更改通知。
【讨论】:
这里是链接,以防有人想阅读更多内容。微软将其删除,但它在此处的网络存档中。 web.archive.org/web/20131129053934/http://msdn.microsoft.com/… 这个答案为我指明了正确的方向,但是在没有示例的情况下仍然需要一段时间才能弄清楚细节。我根据原代码写了一个example。【参考方案4】:您可以使用ObjectDataProvider
类,它是MethodName
属性。它可能看起来像这样:
<Window.Resources>
<ObjectDataProvider x:Key="versionManager" ObjectType="x:Type VersionManager" MethodName="get_FilterString"></ObjectDataProvider>
</Window.Resources>
声明的对象数据提供者可以这样使用:
<TextBox Text="Binding Source=StaticResource versionManager" />
【讨论】:
【参考方案5】:如果您使用的是本地资源,可以参考如下:
<TextBlock Text="Binding Source=x:Static prop:Resources.PerUnitOfMeasure" TextWrapping="Wrap" TextAlignment="Center"/>
【讨论】:
【参考方案6】:可能有两种方法/语法来绑定static
属性。如果 p 是类 MainWindow
中的 static
属性,则 textbox
的 binding
将是:
1.
<TextBox Text="x:Static local:MainWindow.p" />
2.
<TextBox Text="Binding Source=x:Static local:MainWindow.p,Mode=OneTime" />
【讨论】:
【参考方案7】:看看我的项目CalcBinding,它提供给你写复杂的Path属性值表达式,包括静态属性、源属性、Math等。所以,你可以这样写:
<TextBox Text="c:Binding local:VersionManager.FilterString"/>
祝你好运!
【讨论】:
【参考方案8】:从 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; ;
您现在可以像绑定其他任何属性一样绑定您的静态属性:
<TextBox Text="Binding Path=(local:VersionManager.FilterString)"/>
【讨论】:
VersionManager
类可以是静态的,并且一切正常。注意路径定义中的大括号Path=(local:VersionManager.FilterString)
。有谁知道为什么需要它们?
路径定义中需要大括号,因为属性是静态的,见here
@Matt 我怎么知道我的 wpf 版本?
另请注意,与“普通”绑定不同,您不能在此处省略 Path=
【参考方案9】:
.NET 4.5 + 的正确变体
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 绑定(注意大括号是 (),而不是 )
<TextBox Text="Binding Path=(yournamespace:VersionManager.FilterString)" />
【讨论】:
对您的代码稍作更改以正确调用 EventHandler。 尝试了很多不同的解决方案,这个成功了。 PropertyChangedEventHandler 对我有用。干杯。【参考方案10】:最简单的答案(.net 4.5 及更高版本):
static public event EventHandler FilterStringChanged;
static string _filterString;
static public string FilterString
get return _filterString;
set
_filterString= value;
FilterStringChanged?.Invoke(null, EventArgs.Empty);
和 XAML:
<TextBox Text="Binding Path=(local:VersionManager.FilterString)"/>
不要忽略括号
【讨论】:
【参考方案11】:另一种解决方案是创建一个像这样实现 PropertyChanger 的普通类
public class ViewProps : PropertyChanger
private string _MyValue = string.Empty;
public string MyValue
get
return _MyValue
set
if (_MyValue == value)
return;
SetProperty(ref _MyValue, value);
然后在你不会的地方创建一个类的静态实例
public class MyClass
private static ViewProps _ViewProps = null;
public static ViewProps ViewProps
get
if (_ViewProps == null)
_ViewProps = new ViewProps();
return _ViewProps;
现在将其用作静态属性
<TextBlock Text="x:Bind local:MyClass.ViewProps.MyValue, Mode=OneWay" />
如果需要,这里是 PropertyChanger 的实现
public abstract class PropertyChanger : INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
if (object.Equals(storage, value)) return false;
storage = value;
OnPropertyChanged(propertyName);
return true;
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
【讨论】:
以上是关于绑定到静态属性的主要内容,如果未能解决你的问题,请参考以下文章