[wpf] 정적 속성에 바인딩

간단한 정적 문자열 속성을 TextBox에 바인딩하는 데 어려움을 겪고 있습니다.

정적 속성을 가진 클래스는 다음과 같습니다.

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>

모든 것이 컴파일되지만 런타임에 다음 예외가 발생합니다.

‘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. appVersionManager 클래스의 네임 스페이스 (및 어셈블리) 위치로 아래를 정의하십시오 .

<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라는 정적 이벤트를 노출합니다. 정적 속성을 구현하는 클래스는 두 방법 중 하나를 사용하여 속성 변경 알림을 발생시킬 수 있습니다.


답변

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)}"/>


답변

static속성 을 바인딩하는 두 가지 방법 / 구문이있을 수 있습니다 . 경우 p는 A는 static클래스의 속성은 MainWindow다음 binding을 위해이 textbox될 것입니다 :

1.

<TextBox Text="{x:Static local:MainWindow.p}" />

2.

<TextBox Text="{Binding Source={x:Static local:MainWindow.p},Mode=OneTime}" />


답변

ObjectDataProvider클래스와 MethodName속성을 사용할 수 있습니다 . 다음과 같이 보일 수 있습니다 :

<Window.Resources>
   <ObjectDataProvider x:Key="versionManager" ObjectType="{x:Type VersionManager}" MethodName="get_FilterString"></ObjectDataProvider>
</Window.Resources>

선언 된 객체 데이터 공급자는 다음과 같이 사용할 수 있습니다.

<TextBox Text="{Binding Source={StaticResource versionManager}}" />


답변

로컬 리소스를 사용하는 경우 아래와 같이 참조 할 수 있습니다.

<TextBlock Text="{Binding Source={x:Static prop:Resources.PerUnitOfMeasure}}" TextWrapping="Wrap" TextAlignment="Center"/>