2011-01-25 9 views
3

저는 WPF를 처음 사용하고 간단한 앱인 스톱워치를 만들려고합니다. 데이터 바인딩을 수행하지 않으면 제대로 작동합니다. 여기 내 XAML이 있습니다. 여기 간단한 데이터 바인딩이 작동하지 않습니다.

<Window x:Class="StopWatch.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:s="clr-namespace:StopWatch" 
    Title="MainWindow" Height="318" Width="233"> 
<Window.Resources> 
    <s:StopWatchViewModel x:Key="swViewModel" x:Name="swViewModel"></s:StopWatchViewModel> 
</Window.Resources> 
<Grid DataContext="{StaticResource swViewModel}"> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="Auto"/> 
     <RowDefinition Height="auto"/> 
     <RowDefinition Height="128*" /> 
    </Grid.RowDefinitions> 
    <TextBlock Grid.Row="1" Height="49" HorizontalAlignment="Left" Margin="42,50,0,0" Name="txtTime" Text="{Binding Path=Message}" VerticalAlignment="Top" Width="147" FontSize="20" TextAlignment="Center" /> 
    <Button Content="Start" Grid.Row="2" Height="23" HorizontalAlignment="Left" Margin="12,15,0,0" Name="startBtn" VerticalAlignment="Top" Width="58" Click="startBtn_Click" /> 
    <Button Content="Stop" Grid.Row="2" Height="23" HorizontalAlignment="Left" Margin="76,15,0,0" Name="stopBtn" VerticalAlignment="Top" Width="58" Click="stopBtn_Click" /> 
    <Button Content="Reset" Grid.Row="2" Height="23" HorizontalAlignment="Left" Margin="140,15,0,0" Name="resetBtn" VerticalAlignment="Top" Width="59"/> 
</Grid> 
은 MainWindow를

public partial class MainWindow : Window 
{ 
    private StopWatchViewModel stopwatch; 

    public MainWindow() 
    { 
     InitializeComponent(); 
     stopwatch = new StopWatchViewModel(); 
    } 

    private void startBtn_Click(object sender, RoutedEventArgs e) 
    { 
     stopwatch.Start(); 
    } 

    private void stopBtn_Click(object sender, RoutedEventArgs e) 
    { 
     stopwatch.Stop(); 
    } 
} 

의 코드이며, 여기에 내가 잘못 어디서 얻었

class StopWatchViewModel : INotifyPropertyChanged 
{ 
    private DispatcherTimer timer; 
    private Stopwatch stopwatch; 
    private string message; 

    public event PropertyChangedEventHandler PropertyChanged; 

    public string Message 
    { 
     get 
     { 
      return message; 
     } 
     set 
     { 
      if (message != value) 
      { 
       message = value; 
       OnPropertyChanged("Message"); 
      } 
     } 
    } 

    public StopWatchViewModel() 
    { 
     timer = new DispatcherTimer(); 
     stopwatch = new Stopwatch(); 
     timer.Tick += new EventHandler(timer_Tick); 
     timer.Start(); 
     stopwatch.Reset(); 
    } 

    public void Start() 
    { 
     stopwatch.Start(); 
    } 

    public void Stop() 
    { 
     stopwatch.Stop(); 
    } 

    private void timer_Tick(object sender, EventArgs e) 
    { 
     Message = stopwatch.Elapsed.ToString(); // Doesn't work. 
     // Message = "hello"; does not work too! 
    } 

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

} 

모르겠어요 StopWatchViewModel.cs의 코드입니다 .

편집 : 제대로 작동했습니다. 그래서 여기에 누구의 참조를위한 작업 코드가 있습니다.

XAML은 ERNO의 제안에 따라 생성자를 코드 뒤에이

<Window x:Class="StopWatch.MainWindow" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
xmlns:s="clr-namespace:StopWatch" 
Title="MainWindow" Height="318" Width="233"> 
<Grid> // partial code 

과의 원본을 변경 변경합니다.

public MainWindow() 
    { 
     InitializeComponent(); 
     viewModel = new StopWatchViewModel(); 
     this.DataContext = viewModel; 
    } 

고마워요!

답변

3

그냥 같이 귀하의 메시지 속성을 대체하고 그것은 작동합니다

public string Message 
{ 
    get { return (string)GetValue(MessageProperty); } 
    set { SetValue(MessageProperty, value); } 
} 

public static readonly DependencyProperty MessageProperty = 
    DependencyProperty.Register("Message", typeof(string), 
    typeof(MainWindow), new UIPropertyMetadata(String.Empty)); 

편집을 내 솔루션을 게시 한 후에 내가 당신이 뷰 모델 솔루션에 모든 코드를 변경 발견 ... 무시 주시기 또는 첫 번째 코드 세트로 돌아가십시오.

새 코드에서는 코드에 하나, 리소스에 하나씩 ViewModel의 두 인스턴스를 만듭니다. 모든

+0

입력 해 주셔서 감사합니다. 나는 이것을 시도 할 것이다. 바인드 할 수있게되었지만 이제는 속성을 한 번만 업데이트합니다. –

+0

이것은 정확히 문제입니다. 즉, 버튼이 비상 사태 스톱워치를 시작/중지하지만 바인딩이 Resource-ViewModel에 링크되어 있습니다. 리소스를 제거하고 대신 ViewModel을 공개하는 Public 속성 "ViewModel"을 제공해야합니다. 물론이 속성에 바인딩해야합니다. Window에 속성 x : Name = "wnd"를 부여한 다음 Grid의 DataContext-Binding을

+0

과 같이 변경하십시오. . 좋은 전화 이모. –

1

INotifyPropertyChanged를 올바르게 구현하지 않으면 속성의 변경 사항을 알 수 없습니다. 먼저 그렇게해야합니다. 어쩌면 이전에 그 일을 할 때 뭔가를 놓친 것일 수도 있습니다.

+0

public MainWindow() { InitializeComponent(); stopwatch = new StopWatchViewModel(); this.DataContext = stopwatch; } 

이에 변화 생성자 : 당신이 (XAML)

편집 코드의 하나를 조작하고 자원의 하나에 결합 될 때 그것은 좋지 않다 안녕하세요, INotifyPropertyChanged 구현했습니다. 내 게시물도 편집했습니다. –

4

귀하의 문제는 귀하의 재산이 업데이트되었음을 ​​WPF에 알리는 메커니즘이 없다는 것입니다. 기본적으로 여기에 두 가지 옵션이 있습니다.

  1. 메시지를 종속 속성으로 지정하십시오. 메시지가 업데이트 된시기를 알 수 있도록 INotifyPropertyChanged을 구현하십시오.

당신이 일을 INotifyPropertyChanged을 얻기를위한 모든 부분이 있는지 확인하려면, 당신은이 모든했다는 것을 확인하십시오

  1. 이벤트 PropertyChanged을 정의합니다.
  2. 이벤트를 발생시키는 개인 NotifyPropertyChanged 메서드를 만듭니다. 이 메서드는 문자열 매개 변수 (속성 이름)를 가져와 다음과 같이 이벤트를 발생시켜야합니다 : PropertyChanged(this, new PropertyChangedEventArgs(<nameofproperty>). 이 방법을 사용하는 이유는 null 체크와 호출 세부 사항을 한 곳에 두는 것입니다.
  3. 속성 설정자에서 값이 변경된 후에 속성의 올바른 이름 (대/소문자 구분)을 사용하여 NotifyPropertyChanged을 호출합니다.
+0

내 코드를 수정했습니다. 여전히 작동하지 않습니다. 다시 확인해 주시겠습니까? –

+0

여전히 작동하지 않는다면 INotifyPropertyChanged를 다시 구현 한 곳에서 업데이트 된 코드를 확인해야한다고 생각합니다. sinc는 해당 구현에서 오류가 있어야합니다. 위의 코드를 편집하여 코드를 추가하면 알 수 있습니다. –

+0

한 가지 더. 프로그램이 실제로 Tick을 호출하는지 확인하기 위해 Message가 실제로 변경된 tick 메서드 안에 중단 점을 넣으려고 했습니까? (문장이 호출되지 않으면 문제를 설명 할 수 있습니다.) –

관련 문제