정적 속성에 바인딩
간단한 정적 문자열 속성을 텍스트 상자에 바인딩하는 데 어려움을 겪고 있습니다.
정적 속성을 가진 클래스는 다음과 같습니다.
public class VersionManager
{
private static string filterString;
public static string FilterString
{
get { return filterString; }
set { filterString = value; }
}
}
내 xaml 에서이 정적 속성을 텍스트 상자에 바인딩하고 싶습니다.
<TextBox>
<TextBox.Text>
<Binding Source="{x:Static local:VersionManager.FilterString}"/>
</TextBox.Text>
</TextBox>
모든 것이 컴파일되지만 런타임에 다음 예외가 발생합니다.
'Source'특성의 값을 'System.Windows.Markup.StaticExtension'유형의 개체로 변환 할 수 없습니다. 마크 업 파일 'BurnDisk; component / selectversionpagefunction.xaml'의 'System.Windows.Data.Binding'개체에서 오류 57 행 29 위치.
내가 뭘 잘못하고 있는지 알아?
바인딩이 양방향이어야하는 경우 경로를 제공해야합니다. 클래스가 정적이 아닌 경우 정적 속성에 양방향 바인딩을 수행하는 트릭이 있습니다. 리소스에서 클래스의 더미 인스턴스를 선언하고 바인딩의 소스로 사용하십시오.
<Window.Resources>
<local:VersionManager x:Key="versionManager"/>
</Window.Resources>
...
<TextBox Text="{Binding Source={StaticResource versionManager}, Path=FilterString}"/>
그런 정적에는 바인딩 할 수 없습니다. DependencyObject
(또는 구현하는 객체 인스턴스)가 없기 때문에 바인딩 인프라가 업데이트에 대한 알림을받을 방법이 없습니다 INotifyPropertyChanged
.
해당 값이 변경되지 않으면 바인딩을 버리고 속성 x:Static
내에서 직접 사용 하십시오 Text
. 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}"/>
.NET 4.5에서는 정적 속성에 바인딩 할 수 있습니다.
정적 속성을 데이터 바인딩 소스로 사용할 수 있습니다. 정적 이벤트가 발생하면 데이터 바인딩 엔진이 특성 값이 변경되는시기를 인식합니다. 예를 들어 SomeClass 클래스가 MyProperty라는 정적 속성을 정의하면 SomeClass는 MyProperty 값이 변경 될 때 발생하는 정적 이벤트를 정의 할 수 있습니다. 정적 이벤트는 다음 서명 중 하나를 사용할 수 있습니다.
public static event EventHandler MyPropertyChanged;
public static event EventHandler<PropertyChangedEventArgs> StaticPropertyChanged;
첫 번째 경우 클래스는 EventArgs를 이벤트 핸들러로 전달하는 PropertyNameChanged라는 정적 이벤트를 노출합니다. 두 번째 경우, 클래스는 PropertyChangedEventArgs를 이벤트 핸들러로 전달하는 StaticPropertyChanged라는 정적 이벤트를 노출합니다. 정적 속성을 구현하는 클래스는 두 방법 중 하나를 사용하여 속성 변경 알림을 발생시킬 수 있습니다.
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.
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)}"/>
You can use ObjectDataProvider
class and it's MethodName
property. It can look like this:
<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}}" />
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"/>
There could be two ways/syntax to bind a static
property. If p is a static
property in class MainWindow
, then binding
for textbox
will be:
1.
<TextBox Text="{x:Static local:MainWindow.p}" />
2.
<TextBox Text="{Binding Source={x:Static local:MainWindow.p},Mode=OneTime}" />
Right variant for .NET 4.5 +
C# code
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 {})
<TextBox Text="{Binding Path=(yournamespace:VersionManager.FilterString)}" />
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:
<TextBox Text="{c:Binding local:VersionManager.FilterString}"/>
Goodluck!
Leanest answer (.net 4.5 and later):
static public event EventHandler FilterStringChanged;
static string _filterString;
static public string FilterString
{
get { return _filterString; }
set
{
_filterString= value;
FilterStringChanged?.Invoke(null, EventArgs.Empty);
}
}
and XAML:
<TextBox Text="{Binding Path=(local:VersionManager.FilterString)}"/>
Don't neglect the brackets
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.
Let's say you've got a really basic WPF app MainWindow XAML like this,
<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:
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 :)
참고URL : https://stackoverflow.com/questions/936304/binding-to-static-property
'IT' 카테고리의 다른 글
ASP.NET MVC 컨트롤러에서 외부 URI로 리디렉션 (0) | 2020.06.01 |
---|---|
Django DB 설정 '잘못된 구성'오류 (0) | 2020.06.01 |
Enum으로 싱글 톤 구현하기 (Java) (0) | 2020.06.01 |
소품에서 구성 요소 초기화 상태를 반응 (0) | 2020.06.01 |
명령 프롬프트에서 공백을 어떻게 사용합니까? (0) | 2020.06.01 |