web-dev-qa-db-ja.com

静的プロパティへのバインド

単純な静的文字列プロパティをテキストボックスにバインドするのに苦労しています。

静的プロパティを持つクラスは次のとおりです。

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>

すべてがコンパイルされますが、実行時に次の例外が発生します。

属性「ソース」の値をタイプ「System.Windows.Markup.StaticExtension」のオブジェクトに変換できません。マークアップファイル 'BurnDisk; component/selectversionpagefunction.xaml'のオブジェクト 'System.Windows.Data.Binding'でのエラー行57位置29。

私が間違っていることを知っていますか?

162
Anthony Brien

バインディングを双方向にする必要がある場合は、パスを指定する必要があります。クラスが静的でない場合、静的プロパティで双方向バインディングを行うトリックがあります。リソースでクラスのダミーインスタンスを宣言し、バインディングのソースとして使用します。

<Window.Resources>
    <local:VersionManager x:Key="versionManager"/>
</Window.Resources>
...

<TextBox Text="{Binding Source={StaticResource versionManager}, Path=FilterString}"/>
160
Thomas Levesque

そのような静的にバインドすることはできません。 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}"/>
99
Adam Sills

.NET 4.5では、静的プロパティにバインドできます 続きを読む

静的プロパティをデータバインディングのソースとして使用できます。データバインディングエンジンは、静的イベントが発生した場合にプロパティの値がいつ変更されるかを認識します。たとえば、SomeClassクラスがMyPropertyという静的プロパティを定義している場合、SomeClassはMyPropertyの値が変更されたときに発生する静的イベントを定義できます。静的イベントは、次のシグネチャのいずれかを使用できます。

public static event EventHandler MyPropertyChanged; 
public static event EventHandler<PropertyChangedEventArgs> StaticPropertyChanged; 

最初の場合、クラスは、EventArgsをイベントハンドラーに渡すPropertyNameChangedという名前の静的イベントを公開します。 2番目の場合、クラスは、PropertyChangedEventArgsをイベントハンドラーに渡すStaticPropertyChangedという名前の静的イベントを公開します。静的プロパティを実装するクラスは、いずれかの方法を使用してプロパティ変更通知を生成することを選択できます。

38
Jowen

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

ObjectDataProviderクラスを使用でき、そのクラスはMethodNameプロパティです。次のようになります。

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

宣言されたオブジェクトデータプロバイダーは、次のように使用できます。

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

ローカルリソースを使用している場合は、次のように参照できます。

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

staticプロパティをバインドするには、2つの方法/構文があります。 pがクラスstaticMainWindowプロパティである場合、bindingtextboxは次のようになります。

1。

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

2。

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

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

私のプロジェクト CalcBinding を見てください。これは、静的プロパティ、ソースプロパティ、数学などを含む複雑な式をPathプロパティ値に記述することを可能にします。だから、あなたはこれを書くことができます:

<TextBox Text="{c:Binding local:VersionManager.FilterString}"/>

幸運を!

2
Alex141

無駄のない回答(.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)}"/>

括弧を無視しないでください

0
Sean

これらの答えは、良い慣習に従うことを望んでいるが、OPが何かsimpleを望んでいた場合、すべて良いです。 。基本的なGUIアプリに文字列があり、空想なしでアドホックに更新できる場合は、C#ソースで直接アクセスできます。

このような本当に基本的な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>

これは次のようになります。

enter image description here

MainWindow XAMLのソースでは、textBlock.Textget/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----";
        }
    }
}

次に、ボタンをクリックしてそのクリックイベントをトリガーすると、出来上がり!キルロイが表示されます:)

enter image description here

0