2011-11-18 4 views
0

XAML 바인딩을 처음으로 이해하지 못하는 이유를 이해하는 데 어려움을 겪고있는 C# 초보자입니다. 나는 마이크로 소프트의 Data Binding Overview을 따르고있다.문자열에서 XBox 로의 XAML 바인딩이 작동하지 않습니다.

결국 하나의 TextBox가 상태 창으로 사용됩니다. 지금은 그냥 임의의 텍스트 문자열을 쓸 수 있어야합니다. 또한 테스트중인 명령 패턴의 인스턴스가 있습니다. 내 명령에는 누적 계산기에 임의의 숫자를 추가하고 그 결과를 상태보기에 인쇄하는 작업이 포함됩니다. 내 데이터 표현

<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> 

그리고 클래스 :

여기에 메인 애플리케이션 창 내 XAML의

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 이벤트를 실행해야합니까? 바인딩 프레임 워크의 전체적인 포인트는 이벤트가 자동으로 뒤에서 해고되고 소비된다는 것입니다. 하지만 어쩌면 내가 틀렸어.

내 바인딩 구문이 정확하다고 생각하는 명백한 오류가 출력 창에 표시되지 않습니다. 나는 다른 것을 놓치고있다.

하프!

EDIT 동부 서머 타임 13시 14분 감사 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)); 
     } 
    } 
} 

이 코드 경로를 통과했는지 확인하기 위해 디버깅했습니다. 그러나 여전히 운이 없다. 다른 생각?

+0

StaticResource 대신 DynamicResource를 사용하십시오. –

+0

@PankajUpadhyay : 컴파일되지 않습니다. 그리고 "자원"에 대한 생각이 실제로 포인터가 아닐까요? 내 말은,이 TextBox가 항상 동일한 속성을 가리 키길 바랄 것입니다. 그건 절대로 바뀌지 않을 것입니다. 그래서 나는 컴파일 타임에 그것을 설정할 수 있어야합니다. – Tenner

+0

바인딩에서 TextBlock을 TextBox로 변경하고 XAML에서 모든 바인딩을 삭제하십시오. – MBen

답변

2

여전히 StatusViewText에 INotifyPropertyChanged를 구현해야합니다. 바인딩 시스템에서 값을 지속적으로 확인하지 않으므로 상황이 변경 될 때이를 알려야합니다.

+0

감사합니다. 원래 게시물에 추가 된 편집을 참조하십시오. – Tenner

+1

작동 중입니다 : statusText.SetBinding (TextBox.TextProperty, statusViewTextBinding); (TextBlock 대신 TextBox) 및 XAML에서 모든 바인딩을 삭제했습니다. (게시하려는 경우 코드가 있습니다.) – MBen

+0

완벽 ... TextBox 대 TextBlock이었습니다. 도움을 많이 주셔서 감사합니다! – Tenner

1

코드에서 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)); 
     } 
    } 
} 
3

다음은이 작업이 적용해야하는 변화입니다.

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를 지정해야합니다 :

는 여기에 귀하의 ViewModel의 코드입니다. 코드 뒤에 솔루션입니다 : MainWindow를의의 ctor에서, 데이터 컨텍스트 입력 :

this.DataContext = new StatusViewText(); 

XAML에서를, 당신은 당신이 속성 StatusTextString 구속력을 말해야한다. 그것은 데이터 컨텍스트가 StatusViewText의 인스턴스이기 때문에 작동합니다.

Text="{Binding Path=StatusTextString}" 
관련 문제