2016-08-21 43 views
0

我非常抱歉,這個問題是非常基本的。我剛剛學會了WPF,並且我未能簡單地將textbox.text的兩種方式綁定到字符串屬性。綁定簡單的WPF文本框文本TwoWay

XAML代碼:

<Window x:Class="WpfApplication1.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:WpfApplication1" 
    mc:Ignorable="d" 
    Title="MainWindow" Height="350" Width="525"> 
<Grid x:Name="StuInfo"> 
    <TextBox x:Name="textBox" HorizontalAlignment="Left" Height="23" Margin="10,26,0,0" TextWrapping="Wrap" Text="{Binding Path=str,Mode=TwoWay}" VerticalAlignment="Top" Width="120"/> 
    <Button x:Name="button" Content="Check" HorizontalAlignment="Left" Margin="10,67,0,0" VerticalAlignment="Top" Width="75" Click="button_Click"/> 
</Grid> 

C#代碼

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
     str = "OK"; 
    } 

    public string str { get; set; } 

    private void button_Click(object sender, RoutedEventArgs e) 
    { 
     Console.WriteLine(str); 
    } 
} 

首先,文本框不顯示 「OK」,但它是空白。然後,我在文本框中輸入了不同的文本,例如:「blablabla」沒有引號。然後我點擊按鈕來檢查我的str屬性是否已經更新。顯然,str仍然包含「OK」。

我在這裏做錯了什麼?我錯過了什麼讓綁定工作?

回答

1

問題是,你不綁定到Window的代碼隱藏,而是綁定到DataContext。

試試這個:

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
     DataContext = new DC(); 
    } 

    public class DC 
    { 
     public string str { get; set; } 

     public DC() 
     { 
      str = "OK"; 
     } 
    } 
} 

通常情況下,你將有兩個不同的文件,但對於測試,你可以在一個文件中做到這一點。 之後,您的DC(DataContext)應該實現INotifyPropertyChanged接口。

嘗試查找有關MVVM一些文章這樣http://www.codeproject.com/Articles/165368/WPF-MVVM-Quick-Start-Tutorial

+0

或者你可以設置你的DataContext到這個,但這真是個壞主意。你應該分開你的ViewModel和你的視圖。 –

+0

因此,設置DataContext解決了這個問題。無論如何,我可以使它工作而不必實例化一個對象,直接使用字符串屬性?這個問題的答案是將DataContext設置爲這個嗎? – kurakura88

+1

你可以綁定到窗口後面的代碼,沒有什麼錯:'public MainWindow {InitializeComponent(); ** DataContext = this; **}' – slugster

1

作爲一個初來乍到WPF,這一切的綁定和DataContext的爵士可能會相當混亂。讓我們先從你的綁定表達式首先...

<TextBox Text="{Binding Path=str, Mode=TwoWay}"/>

這是什麼要說的是,你想你的Text屬性綁定到無論TextBoxDataContext是。 DataContext本質上是您的TextBox從中獲取數據的「事情」。現在這是蹭。 DataContext如果未明確設置,則從視覺樹中的「上方」元素繼承。在您的代碼中,TextBoxGrid元素繼承它的DataContext,該元素繼而從Window元素繼承它的DataContext。鑑於DataContext未在您的Window中設置,將應用DataContext屬性的默認值,即nullDataContext也未在窗口的任何子元素中設置,它們通過繼承將該窗口的所有子項的DataContext設置爲null

重要的是要注意,您在綁定表達式中忽略了Source屬性。

<TextBox Text="{Binding Source=left_out, Path=str, Mode=TwoWay}"/>

當該屬性被遺漏,綁定源隱含爲元素DataContext,在這種情況下爲空,基於上述的理由。基本上,你的表達在這裏說的是,你想要綁定您的文本屬性DataContext.str由WPF解決的是null.str

好的,很酷。現在,我們如何設置您的TextBox.TextDataContext綁定到該窗口的代碼隱藏,所以我們可以得到str屬性?有幾種方法可以做到這一點,但出於我們的目的,我們將專注於在TextBox.Text屬性的綁定中明確地設置它。現在,綁定有三種不同的「源」類型屬性。 「源」是我們希望我們的控件/元素的綁定從其獲取數據的位置。我們有Source,RelativeSourceElementName。我們只在這裏專注於ElementName,但其他人對研究和理解至關重要。

因此,讓我們命名我們的Window元素,以便我們可以通過ElementName屬性訪問它。

<Window x:Class="WpfApplication1.MainWindow" 
     x:Name="_window" 
     ... 

現在,我們可以設置在TextBox.TextElementName屬性綁定來引用窗口。

<TextBox Text="{Binding ElementName=_window, Path=str, Mode=TwoWay}"/>

這意味着綁定試圖解決它綁定時會尋找_window.str財產。此時,您仍然可能看不到TextBox中反映的str值。這是因爲它的值是在窗口構造函數中的InitializeComponent方法之後設置的。這個函數是第一次解析綁定的地方。如果您在致電InitializeComponent之前設置str的值,則會看到TextBox中反映的值。

這使我們看到依賴屬性。現在,只知道依賴屬性內置了更改通知,您的綁定需要它,以便它知道綁定已更改何時以及何時再次解析綁定值。是的,你可以在你的代碼中使用INotifyPropertyChanged,但在這種情況下使用DependencyProperties有很好的參數,這隻會混淆這個問題。但是,這是另一個必須理解的東西。

這裏是您的str屬性DependencyProperty的代碼。

public static readonly DependencyProperty StrProperty 
    = DependencyProperty.Register("Str", typeof(string), typeof(MainWindow), 
     new FrameworkPropertyMetadata(FrameworkPropertyMetadataOptions.BindsTwoWayByDefault)); 
public string Str 
{ 
    get{return (string)GetValue(StrProperty);} 
    set{SetValue(StrProperty,value);} 
} 

現在,你可以設置像這樣的價值,並把它通過綁定到您TextBox反映。

public MainWindow() 
{ 
    InitializeComponent(); 
    Str = "OK"; 
} 

此時,一切都會好的。我希望這可以幫到你。我花了一段時間纔得到WPF的支持。我的建議是儘可能多地閱讀DataContext,BindingDependencyProperty,因爲這些是WPF的核心。祝你好運!

+0

感謝您花時間向我解釋。那麼這是否意味着如果我爲「綁定源」設置一個「DataContext」以使其作爲替代方案工作?在你的例子中,我可以設置「{綁定源= _window ...}」並使其工作? – kurakura88

+0

非常歡迎。感謝您的幫助!至於你的問題,答案是否定的。 'ElementName'屬性是唯一可以與'Window'的'x:Name'屬性一起使用的屬性。 '源'用於靜態和動態資源,這是更先進一點。 –

+0

它可能有助於設想'源'只是明確解析綁定對象或「源」的三種方法之一。我知道這很混亂。你可以使用'Source','RelativeSource'或'ElementName',它們都是互斥的。您也可以不使用這些,並將「源」區域留爲空白,並將其解析爲「DataContext」。注意'Source'和「Source」之間的區別。 「Source」是綁定的實際屬性,「Source」是用於引用綁定的基礎源對象的語義。 –