2013-08-05 4 views
1

У меня есть проект WPF, в котором у меня есть 4 TexBlock. Я хочу изменить Text каждого TextBlock через Binding.WPF Xaml Binding не работает

До сих пор у меня есть мой код XAML:

<Grid> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="*"/> 
     <RowDefinition Height="*"/> 
     <RowDefinition Height="*"/> 
     <RowDefinition Height="*"/> 
    </Grid.RowDefinitions> 
    <TextBlock x:Name="First" Text="{Binding FirstString}" Grid.Row="0"/> 
    <TextBlock x:Name="Second" Text="{Binding SecondString}" Grid.Row="1"/> 
    <TextBlock x:Name="Third" Text="{Binding ThirdString}" Grid.Row="2"/> 
    <TextBlock x:Name="Fourth" Text="{Binding FourthString}" Grid.Row="3"/> 
</Grid> 

И в моем коде я есть:

public partial class MainWindow : Window 
{ 
    public string FirstString { get; set; } 
    public string SecondString { get; set; } 
    public string ThirdString { get; set; } 
    public string FourthString { get; set; } 

    public MainWindow() 
    { 
     InitializeComponent();  

     FirstString = "First"; 
     SecondString = "Second"; 
     ThirdString= "Third 
     FourthString= "Fourth"; 
    } 
} 

Но Binding не работает вообще. Я что-то делаю неправильно? Пожалуйста помоги. Спасибо заранее.

EDIT: 

Выполнив Крис Мантия предложение глядя на debbuger (у меня был установлен на предупреждение сор Привязка) я получаю следующее сообщение об ошибке:

System.Windows.Data Information: 10 : Cannot retrieve value using the binding and no valid fallback value exists; using default instead. BindingExpression:Path=FirstString; DataItem=null; target element is 'TextBlock' (Name='First'); target property is 'Text' (type 'String') 
+1

Есть ли что-нибудь в окне вывода? –

+0

Ничего. И я не могу найти причину. – oimitro

+1

Можете ли вы включить информацию о привязке данных в окне вывода и посмотреть, есть ли какие-либо детали? (Меню «Сервис» -> «Параметры» -> «Отладка» -> «Окно вывода» -> Параметры трассировки WPF -> «Связывание данных», установите что-то вроде Verbose или All) –

ответ

4

Есть несколько вещей, которые неверны. Разметка Binding будет рассматривать объект в свойстве DataContext элемента управления. Это свойство наследует DataContext от объявления родителя, если не указано иное. Из этой позиции это null для управления Window.

Возможны две проблемы. Вы можете либо установить DataContext явно в коде-за или XAML

// In XAML 
<Window DataContext={Binding RelativeSource={RelativeSource Self}}> 

or 

// In the code-behind 
DataContext = this; 

Другая проблема заключается в том, что привязка применяется при инициализации. Первоначально ваши свойства пусты. После фазы InitializeComponent элементы управления будут «привязываться» к свойствам (которые пусты). Когда вы устанавливаете свои свойства после этого, элементы управления не имеют возможности узнать, что он изменился. Для этого есть два механизма. На уровне управления вы можете сделать эти свойства как DependencyProperty или реализовать интерфейс INotifyPropertyChanged и поднять изменения.Если вы хотите идти по пути INPC, вы можете реализовать свои свойства и окна, как, например:

public partial class MainWindow : INotifyPropertyChanged 
{ 
    private string firstString; 
    private string secondString; 
    private string thirdString; 
    private string fourthString; 

    public string FirstString 
    { 
     get { return firstString; } 
     set 
     { 
      firstString = value; 
      RaisePropertyChanged("FirstString"); 
     } 
    } 

    public string SecondString 
    { 
     get { return secondString; } 
     set 
     { 
      secondString = value; 
      RaisePropertyChanged("SecondString"); 
     } 
    } 

    public string ThirdString 
    { 
     get { return thirdString; } 
     set 
     { 
      thirdString = value; 
      RaisePropertyChanged("ThirdString"); 
     } 
    } 

    public string FourthString 
    { 
     get { return fourthString; } 
     set 
     { 
      fourthString = value; 
      RaisePropertyChanged("FourthString"); 
     } 
    } 

    public MainWindow() 
    { 
     DataContext = this; 
     InitializeComponent(); 

     FirstString = "First"; 
     SecondString = "Second"; 
     ThirdString = "Third"; 
     FourthString = "Fourth"; 
    } 

    public event PropertyChangedEventHandler PropertyChanged = delegate { }; 

    private void RaisePropertyChanged(string propertyName) 
    { 
     var handlers = PropertyChanged; 

     handlers(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 
+0

Нет необходимости делать это, поскольку код находится за xaml, и он будет автоматически уведомлять об изменении контекста ... –

+2

@Arun Я не следую вашей логике Если свойства не являются INPC, а не свойствами зависимостей, изменение свойства не будет отражено в пользовательском интерфейсе. В этом простом случае установка «DataContext = this» после установки свойства будет работать, потому что «DataContext» является свойством зависимости, но никаких дальнейших изменений кода не будет отражено. –

+0

public partial class MainWindow: INotifyPropertyChanged, Thats it !!! – oimitro

2

Если не указано иное, путь вязка относительно элемента DataContext. В вашем случае, я подозреваю, что вы не указали DataContext вообще ...

Поскольку свойства объявляются в самом MainWindow классе, проще исправить это добавить:

DataContext = this; 

в конце конструктора.

+0

да, я собираюсь ответить –

+0

Я использовал DataContext = this; но все равно ничего. – oimitro

+0

Переместить InitializeComponent(); в нижней части вашего конструктора, то вы должны хотя бы что-то увидеть. Николя прав. – Golvellius

2

Поскольку вы не уведомите, что FirstString, SecondString, ThirdString и FourthString изменены, изменение не будет отражено в пользовательском интерфейсе. Вы можете либо реализовать INotifyPropertyChanged, либо иметь дело с DependencyProperty

Установите Datacontext, также.

IMHO DependencyProperty лучше для этого использования. Вот пример:

public partial class MainWindow : Window 
{ 
    #region Public 
    public string FirstString 
    { 
     get { return (string)GetValue(FirstStringProperty); } 
     set { SetValue(FirstStringProperty, value); } 
    } 
    public string SecondString 
    { 
     get { return (string)GetValue(SecondStringProperty); } 
     set { SetValue(SecondStringProperty, value); } 
    } 
    public string ThirdString 
    { 
     get { return (string)GetValue(ThirdStringProperty); } 
     set { SetValue(ThirdStringProperty, value); } 
    } 
    public string FourthString 
    { 
     get { return (string)GetValue(FourthStringProperty); } 
     set { SetValue(FourthStringProperty, value); } 
    } 

    #region Dependency Properties 
    public static readonly DependencyProperty FirstStringProperty = DependencyProperty.Register("FirstString", typeof(string), typeof(MainWindow), new PropertyMetadata("default value")); 
    public static readonly DependencyProperty SecondStringProperty = DependencyProperty.Register("SecondString", typeof(string), typeof(MainWindow), new PropertyMetadata("default value")); 
    public static readonly DependencyProperty ThirdStringProperty = DependencyProperty.Register("ThirdString", typeof(string), typeof(MainWindow), new PropertyMetadata("default value"));   
    public static readonly DependencyProperty FourthStringProperty = DependencyProperty.Register("FourthString", typeof(string), typeof(MainWindow), new PropertyMetadata("default value")); 
    #endregion 
    #endregion 

    public MainWindow() 
    { 
     InitializeComponent();  

     FirstString = "First"; 
     SecondString = "Second"; 
     ThirdString= "Third"; 
     FourthString= "Fourth"; 

     this.DataContext = this; 
    } 
} 
+0

Вам не хватает 2-го кавычки в 'ThirdString =" Третий' внутри вашего примера ctor – Mafii

+0

Спасибо, отредактирован :) –

0

Я хотел бы предложить вам создать еще один класс MainWindowViewModel.

public class MainWindowViewModel 
{ 
    public string FirstString { get; set; } 
    public string SecondString { get; set; } 
    public string ThirdString { get; set; } 
    public string FourthString { get; set; } 

    public MainWindowViewModel() 
    {  
     FirstString = "First"; 
     SecondString = "Second"; 
     ThirdString= "Third 
     FourthString= "Fourth"; 
    } 
} 

Затем установите объект DataContext объекта MainWindow перед вызовом show в классе окна.

MainWindow wnd = new MainWindow(); 
wnd.DataContext = new MainWindowViewModel(); 
wnd.Show(); 

Вы можете сделать это последний бит, удалив StartupUri = «MainWindow.xaml» из вашего App.xaml и создать и показать главное окно вручную перекрывая OnStartup в App.xaml.cs.

+0

@Sinon Belanger В классе MainWindowViewModel отсутствует метод InitializeComponent(). – Zenchovey

+0

Ох. Сожалею. Не понимал, что это была модель взгляда. Удаление моего комментария. –

0

это должно быть что-то вроде этого, чтобы работать,

<Grid> 
      <Grid.RowDefinitions> 
       <RowDefinition Height="*"/> 
       <RowDefinition Height="*"/> 
       <RowDefinition Height="*"/> 
       <RowDefinition Height="*"/> 
      </Grid.RowDefinitions> 
      <TextBlock x:Name="First" Text="{Binding FirstString}" Grid.Row="0"/> 
      <TextBlock x:Name="Second" Text="{Binding SecondString}" Grid.Row="1"/> 
      <TextBlock x:Name="Third" Text="{Binding ThirdString}" Grid.Row="2"/> 
      <TextBlock x:Name="Fourth" Text="{Binding FourthString}" Grid.Row="3"/> 
     </Grid> 

и C# код будет похож,

public string FirstString { get; set; } 
public string SecondString { get; set; } 
public string ThirdString { get; set; } 
public string FourthString { get; set; } 

public MainWindow() 
{ 
    InitializeComponent();  

    FirstString = "First"; 
    SecondString = "Second"; 
    ThirdString = "Third"; 
    FourthString= "Fourth"; 
    this.DataContext = this; //here you set the context to current instance of window 

} 
Смежные вопросы