簡體   English   中英

從字符串到TextBox的XAML綁定不起作用

[英]XAML binding from a string to TextBox not working

我是一名C#新手,他在理解為什么他第一次嘗試理解XAML綁定不起作用時遇到了問題。 我正在關注Microsoft的數據綁定概述

我只有一個TextBox,它將最終用作狀態窗口。 現在,我只想能夠在其中寫入任意文本字符串。 我也有一個正在測試的命令模式的實例。 我的命令涉及將一個隨機數添加到累加器,然后將結果打印到狀態視圖。

這是主應用程序窗口的XAML:

<Window x:Class="Experiment.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:c="clr-namespace:Experiment"
        Title="Test" Height="500" Width="700" Name="Test" Closing="Test_Closing" DataContext="{Binding ElementName=statusText}" xmlns:my="clr-namespace:Experiment">
    <Window.Resources>
        <c:StatusViewText x:Key="statusViewText" />
    </Window.Resources>
    <DockPanel HorizontalAlignment="Stretch" Margin="0,0,0,0" Width="Auto">
        <!-- Elements deleted for brevity. -->
        <TextBox Margin="5,5,5,5" Name="statusText" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" AcceptsReturn="True" AcceptsTab="True" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" FontFamily="Courier New" FontSize="12"
                 Text="{Binding Source={StaticResource statusViewText}, Path=statusTextString, Mode=OneWay}"/>
    </DockPanel>
</Window>

和代表我的數據的類:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Experiment {
    public class StatusViewText {
        public StringBuilder statusText { get; set; }
        public String statusTextString { get; set; }

        public StatusViewText() {
            statusText = new StringBuilder();
        }

        public void Append(string s) {
            if (s != null) {
                statusText.Append(s);
            }

            statusTextString = statusText.ToString();
        }

        public void AppendLine(string s) {
            if (s != null) {
                statusText.AppendLine(s);
            }

            statusTextString = statusText.ToString();
        }
    }
}

最終,我將在這里使用StringBuilder的適當轉換器,但是在探索這種復雜性之前,我想先了解一下原理。

如果我的理解是正確的(顯然不是),那么所有這些都應該起作用。 綁定目標是TextBox,目標屬性是Text屬性。 綁定源是StatusViewText類的statusTextString屬性。 但是,當我運行命令(並調試並查看StatusViewText.statusTextString正在更新)時,TextBox不會更新。

我以為自己可能需要顯式添加綁定,因此我嘗試在主窗口構造函數的InitializeComponent()之后添加此綁定:

        statusViewText = new StatusViewText();
        Binding statusViewTextBinding = new Binding("statusTextString");
        statusViewTextBinding.Source = statusViewText;
        statusText.SetBinding(TextBlock.TextProperty, statusViewTextBinding);

但這也不起作用。

我是否需要觸發PropertyChanged事件? 我認為綁定框架的全部目的是自動觸發事件並在幕后消耗事件; 但也許我也是錯的。

在“輸出”窗口中沒有出現明顯的錯誤,這使我相信我的綁定語法是正確的。 我只是想念其他東西。

編輯13:14 EDT謝謝mben

好吧,我做到了。 添加了以下內容:

public class StatusViewText : INotifyPropertyChanged {
    public void Append(string s) {
        if (s != null) {
            statusText.Append(s);
        }

        statusTextString = statusText.ToString();
        NotifyPropertyChanged("statusTextString");
    }

    public void AppendLine(string s) {
        if (s != null) {
            statusText.AppendLine(s);
        }

        statusTextString = statusText.ToString();
        NotifyPropertyChanged("statusTextString");
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(String info) {
        if (PropertyChanged != null) {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }
}

我調試以驗證它是否正在通過此代碼路徑。 但是仍然沒有運氣。 還有其他想法嗎?

這是您需要應用使其生效的更改。

這是您的ViewModel的代碼:

public class StatusViewText : INotifyPropertyChanged
{
    public StatusViewText()
    {
        // At least, I have a default value
        this.StatusTextString = "Hello world";
    }

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

    private string statusTextString;
    public string StatusTextString
    {
        get { return this.statusTextString; }
        set
        {
            this.statusTextString = value;
            this.OnPropertyChanged("StatusTextString");
        }
    }
}

您必須指定窗口的DataContext。 后面的代碼是一個解決方案:在MainWindow的ctor中,填充數據上下文:

this.DataContext = new StatusViewText();

在XAML中,您應該說對屬性StatusTextString的綁定。 之所以有效,是因為數據上下文是StatusViewText的實例。

Text="{Binding Path=StatusTextString}"

您仍然需要在StatusViewText上實現INotifyPropertyChanged。 綁定系統不會連續檢查這些值,您需要在情況發生變化時通知它。

請注意,您正在代碼中創建一個實例,該實例與Xaml中表示的實例不同。 您可以通過在StatusViewText的構造函數中設置一個斷點來證明這一點。

將此片段放入MainWindow的構造函數中...

        StatusViewText o = (StatusViewText)FindResource("statusViewText") as StatusViewText;
        if(o!=null)
        {
            o.Append("hello");   
        }

這將影響您的類的正確實例。

您還應該更改班級,使其看起來像這樣……

public  class StatusViewText:INotifyPropertyChanged
{
    public StringBuilder statusText { get; set; }
    private string _statusTextString;
    public String statusTextString
    {
        get { return _statusTextString; }
        set 
        { 
            _statusTextString = value; 
            OnPropertyChanged("statusTextString");
        }
    }
    public StatusViewText()
    {
        statusText = new StringBuilder();
    }
    public void Append(string s)
    {
        if (s != null)
        {
            statusText.Append(s);
        }
        statusTextString = statusText.ToString();
    }
    public void AppendLine(string s)
    {
        if (s != null)
        {
            statusText.AppendLine(s);
        }
        statusTextString = statusText.ToString();
    }
    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(string prop)
    {
        if(PropertyChanged!=null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(prop));
        }
    }
} 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM