2013-08-05 182 views
1

好吧,我有一個WPF項目,其中我有4 TexBlock。我想要的是通過Binding更改每個TextBlockTextWPF Xaml綁定不起作用

到目前爲止,我有我的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後(我不得不設置爲警告SOR綁定)我得到以下錯誤:

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跟蹤設置 - >數據綁定,設置爲類似於詳細或全部) –

回答

4

有幾件事情是不正確的。 Binding標記將查看控件的DataContext屬性中的對象。除非另有說明,此屬性繼承聲明父級的DataContext。開箱即用,對於Window控件,這是null

這個問題有兩種選擇。您可以設置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而不是依賴屬性,屬性的改變將不會反映到UI中,在這種簡單的情況下,設置'DataContext = this'設置屬性後會起作用,因爲'DataContext'是一個依賴項屬性,但是代碼中的任何進一步修改都不會被反映出來。 –

+0

public partial class MainWindow:INotifyPropertyChanged,That's it !!! – oimitro

2

除另有規定外,綁定的路徑相對於元素的DataContext。在你的情況,我懷疑你沒有指定DataContext在所有...

由於屬性在MainWindow類本身聲明的,最簡單的解決方法是添加:

DataContext = this; 

末的構造函數。

+0

是的同樣我要回答 –

+0

我用DataContext = this;但仍然沒有。 – oimitro

+0

Move InitializeComponent();到構造函數的底部,那麼你至少應該看到一些東西。尼古拉斯是正確的,但。 – Golvellius

2

由於您未通知FirstString,SecondString,ThirdStringFourthString已更改,因此更改將不會反映在用戶界面中。您可以執行INotifyPropertyChanged或處理DependencyProperty

設置您的Datacontext也是如此。

恕我直言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

您在ctor示例中的'ThirdString =「Third'處缺少第二個引用標記 – 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"; 
    } 
} 

然後在調用窗口類的show之前設置MainWindow對象的DataContext。

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

你可以從你的App.xaml中取出的StartupUri =「MainWindow.xaml」做最後一位,創造並通過App.xaml.cs.覆蓋OnStartup手動顯示主窗口

+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 

}