Ошибка привязки данных - помогите мне начать с простого примера - PullRequest
1 голос
/ 17 октября 2008

ОК ... Я - парень из VB.NET WinForms, пытающийся понять WPF и всю его удивительность. Я пишу базовое приложение в качестве учебного опыта, и я читаю много информации и смотрю обучающие видео, но я просто не могу начать с простого DataBinding, и я знаю, что мне не хватает какой-то базовой концепции. Как бы мне это ни нравилось, у меня не было этого «Ага!» момент при просмотре исходного кода пока нет.

Итак ... В моем классе Window я определил пользовательскую строку Property. Когда я захожу в Blend, я пытаюсь привязать текст TextBox к этому свойству, но мое свойство не отображается в Blend как то, что доступно для привязки.

Может кто-нибудь сказать мне, что мне нужно добавить в мой код / ​​XAML ниже ... и самое главное, почему?

Мой XAML:

<Window x:Class="Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <Grid>
        <TextBox Text="How do I Bind my SomeText property here?"></TextBox>
    </Grid>
</Window>

Код моего окна:

Class Window1 

    Private _sometext As String = "Hello World"

    Public Property SomeText() As String
        Get
            Return _sometext
        End Get
        Set(ByVal value As String)
            _sometext = value
        End Set
    End Property

End Class

Ответы [ 4 ]

6 голосов
/ 17 октября 2008

Вот как вам нужно изменить свой XAML (код в порядке).

<Window x:Class="Window1"    
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"    
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"    
            Title="Window1" Height="300" Width="300" 
            DataContext="{Binding RelativeSource={RelativeSource Self}}">    
      <Grid>        
          <TextBox Text="{Binding SomeText}">
          </TextBox>    
      </Grid>
    </Window>

Чтобы понять привязки в WPF, вам необходимо понять DataContext. Каждый элемент имеет свойство DataContext, и любой объект, который вы помещаете в это свойство, становится источником данных любых привязок, для которых не указан явный источник данных. Значение DataContext наследуется от родительского объекта (поэтому в этом случае TextBox наследует DataContext Grid, который наследует DataContext окна). Поскольку вы хотите обратиться к свойству окна, вам нужно установить DataContext так, чтобы он указывал на экземпляр Window, что я и делаю в атрибуте DataContext окна.

Вы также можете изменить источник данных для отдельных привязок, используя синтаксис Source = или RelativeSource = в элементе {Binding}.

5 голосов
/ 17 октября 2008

Для привязки данных полезно подумать о нескольких вещах:

  1. Исходный объект
  2. Целевой объект (который должен быть DependencyObject)
  3. Исходное свойство (свойство исходного объекта, участвующее в привязке)
  4. Целевое свойство (которое должно быть свойством зависимости)

В вашем примере кода:

  1. Исходный объект = Window1
  2. Целевой объект = TextBox
  3. Свойство источника = свойство SomeText
  4. Целевое свойство = Текст

Расширение разметки Binding входит в свойство Target объекта Target.

Вот картинка, которая иллюстрирует вышесказанное:

alt text

Проверьте следующий код (один из способов решения этой проблемы):

<Window
    x:Class="WpfApplication2.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Name="theWindow"
    Title="Window1"
    Height="300"
    Width="300"
>
    <Grid>
        <StackPanel>
            <TextBox Text="{Binding ElementName=theWindow, Path=SomeText}"/>
            <Button
                Width="100"
                Height="25"
                Content="Change Text"
                Click="Button_Click"
            />
        </StackPanel>
    </Grid>
</Window>

В расширении разметки Binding я определил источник, используя ElementName ..., который позволяет вам использовать другой элемент в вашем визуальном дереве в качестве источника. При этом мне также пришлось дать окну имя с атрибутом x: Name.

Есть несколько способов определить источник с помощью Binding (то есть Source, ElementName, DataContext) ... ElementName - это только один способ.

Следует отметить, что свойство Source не обязательно должно быть свойством Dependency, но в противном случае свойство Target не будет обновляться ... без какой-либо специальной помощи. Проверьте следующий фрагмент кода (мои извинения это C #, это было быстрее для меня). В нем вы увидите, как я реализую INotifyPropertyChanged. Это позволяет исходному объекту сказать, что что-то изменилось ... и привязка данных достаточно умна, чтобы следить за этим. Таким образом, если вы нажмете кнопку (из приведенного здесь примера кода), она обновит TextBox. Без реализации этого интерфейса (и если вы нажмете кнопку), TextBox не будет обновляться.

Надеюсь, это поможет.

/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window, INotifyPropertyChanged
{
    public Window1()
    {
        InitializeComponent();
    }

    private string _someText = "Hello World!";
    public string SomeText
    {
        get { return _someText; }
        set
        {
            _someText = value;
            OnNotifyPropertyChanged("SomeText");
        }
    }

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;
    private void OnNotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    #endregion

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        this.SomeText = "Goodbye World!";
    }
}
1 голос
/ 17 октября 2008

WPF DataBinding - очень мощная функция. Я предлагаю прочитать некоторые уже существующие статьи в Интернете, такие как

Очень полезным для меня был также блог Беатрисы Косты о привязке данных .

0 голосов
/ 29 декабря 2008

Привязка данных со свойством CLR требует дополнительного шага. Вы должны реализовать INotifyPropertyChanged и запускать событие PropertyChanged при каждом изменении этого свойства CLR. Это не заставит его появиться в Blend, но вы можете связать свойство, используя Text = "{Binding SomeText}" и установив DataContext окна в ваш объект.

Есть альтернатива. Вместо использования привязки данных .NET рассмотрим Update Controls .NET . Это проект с открытым исходным кодом, который заменяет привязку данных и не требует INotifyPropertyChanged. Отличительной особенностью средств управления обновлениями является то, что они могут видеть промежуточную бизнес-логику. С INotifyPropertyChanged вы должны перехватывать и перезапускать события.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...