Связывание со статическим свойством

Мне трудно связать простое статическое строковое свойство с 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>

Все компилируется, но во время выполнения я получаю следующее исключение:

Невозможно преобразовать значение в атрибут "Источник" к объекту типа 'System.Windows.Markup.StaticExtension. Ошибка на объекте 'System.Windows.Data.Binding' в файл разметки 'BurnDisk; компонент /selectversionpagefunction.xaml' Строка 57, позиция 29.

Есть идеи, что я делаю не так?

Ответ 1

Если привязка должна быть двусторонней, вы должны указать путь. Там есть трюк для двусторонней привязки к статическому свойству, если класс не статичен: объявите фиктивный экземпляр класса в ресурсах и используйте его как источник привязки.

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

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

Ответ 2

Вы не можете привязываться к такой статике. Невозможно получить уведомление об обновлениях инфраструктуры привязки, поскольку там не задействован 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}"/>

Ответ 3

В .NET 4.5 можно связать со статическими свойствами, прочитать больше

Вы можете использовать статические свойства в качестве источника привязки данных. механизм привязки данных распознает, когда значение свойства изменяется, если статическое событие. Например, если класс SomeClass определяет статическое свойство MyProperty, SomeClass может определять статическое событие который возникает при изменении значения MyProperty. Статическое событие может использовать одну из следующих подписей:

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

Обратите внимание, что в первом случае класс предоставляет статическое событие с именем PropertyNameChanged, который передает EventArgs обработчику событий. Во втором случае класс предоставляет статическое событие с именем StaticPropertyChanged, который передает PropertyChangedEventArgs в обработчик события. Класс, реализующий статическое свойство, может выбрать для повышения уведомлений об изменении свойств с помощью любого метода.

Ответ 4

Начиная с 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)}"/>

Ответ 5

Вы можете использовать класс ObjectDataProvider и его свойство MethodName. Это может выглядеть так:

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

Объявленный поставщик данных объекта может использоваться следующим образом:

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

Ответ 6

Если вы используете локальные ресурсы, вы можете обратиться к ним, как показано ниже:

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

Ответ 7

Для привязки свойства static может существовать два способа/синтаксиса. Если p является свойством static в классе MainWindow, то binding для textbox будет:

1.

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

2.

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

Ответ 8

Правильный вариант для.NET 4.5 +

Код С#

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

Ответ 9

Посмотрите на мой проект CalcBinding, который предоставляет вам возможность писать сложные выражения в значение свойства Path, включая статические свойства, исходные свойства, Математика и другие. Итак, вы можете написать это:

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

Гудлак!

Ответ 10

Все эти ответы хороши, если вы хотите следовать хорошим соглашениям, но OP хотел чего-то простого, чего я и хотел, вместо того, чтобы иметь дело с шаблонами проектирования GUI. Если все, что вам нужно сделать, это добавить строку в базовое приложение с графическим интерфейсом, вы можете обновить ad-hoc без каких-либо сложностей, вы можете просто получить к ней доступ прямо в исходном коде С#.

Допустим, у вас есть действительно простое приложение 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

В вашем исходном XAML файле MainWindow у вас может быть что-то вроде этого, где все, что мы делаем, изменяя значение напрямую с помощью textBlock.Text get/set textBlock.Text:

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

Ответ 11

Самый простой ответ (.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)}"/>

Не пренебрегайте скобками