2010-12-29 5 views
2

카운트 다운 타이머를 구현 중입니다. 나는 DispatcherTimer을 사용하여 시간을 보여주는 TextBlock을 가지고있다.WPF : XAML에서 코드의 변수를 속성 값으로 사용하는 방법?

해당 TextBlockFontSize 속성에 대한 애니메이션을 만들고 싶습니다. 나는 그 값이 타이머가 오후 9시를 보여줄 때 300pt로 증가하기를 원한다. 따라서 응용 프로그램을 실행하고 계속 증가 할 때마다 8pt로 시작하여 FontSize이 시작되고 실시간이 오후 9시에 도달하면 FontSize은 300pt가되어야합니다.

다음은 그 그림입니다. 응용 프로그램이 실행되면 그 순간부터 9pm에 도달하는 데 걸리는 시간 (초)이 계산됩니다. 결과는 변수 timeToGetTo9pm에 의해 저장됩니다. 내가 직면 한 문제는 XAML에서 애니메이션을 만들 때 Duration 속성에 timeToGetTo9pm을 설정하는 방법을 모르겠다는 것입니다.

아이디어가 있으십니까? 또한, 내 접근 방식이 어리 석거나 혼란 스럽다면, 더 나은 것을 추천 해 주시기 바랍니다. 감사.

위임 본문 :

private void dispatcherTimer_Tick(object sender, EventArgs e) 
{ 
    DateTime currentTime; 
    double timeToNewYearInMiliseconds; 

    currentTime = DateTime.Now; 

    //targetTime is a DateTime object set elsewhere, 
    //It represents the 9pm mentioned in the question body 
    if (DateTime.Compare(targetTime, currentTime) > 0) 
    { 
     timeToNewYearInMiliseconds = targetTime.Subtract(currentTime).TotalMilliseconds; 
     percent = 100/timeToNewYearInMiliseconds; 
     PercentageComplete = percent; 
    } 
} 
+0

chibacity은 확실히 밖으로 방법을 제공하고 있습니다.제 경우를 해결했지만 XAML에서 코드의 변수를 속성 값으로 사용하는 방법을 배우고 싶습니다. – Boris

+0

@ 보리스 xaml의 코드 숨김에서 속성을 사용하는 예제 코드로 답변을 업데이트했습니다. –

답변

3

왜 뒤에-코드 당신의 ViewModel \에 'TimerFontSize'속성을 가지고 있고 그것을 텍스트 상자의 폰트 크기를 결합하지.

FontSize="{Binding TimerFontSize, Mode=OneWay}" 

타이머가 틱하면 글꼴 크기를 다시 계산하고 'TimerFontSize'속성을 설정하십시오. 'TimerFontSize'에 대해 INotifyPropertyChanged를 구현 한 경우 TextBox 바인딩은 자동으로 글꼴 크기를 업데이트하고 변경합니다.

이 패턴은 타이머를 사용하고 데이터 바인딩을 사용하여 애니메이션을 구동합니다.

업데이트

난 당신이 다시이 무슨 뜻인지 참조하십시오. 데이터 표현에서 시각적 표현을 분리합니다. 제 제안은 쉬운 방법입니다. 노출 된 속성을 경과 시간 또는 카운트 다운 값으로 설정 한 다음 ValueConverter을 사용하여 FontSize를 가져와이를 정리할 수 있습니다. 이것은 데이터를 분리하고 개념을 보게됩니다.

다음은 코드 숨김에 속성을 표시하는 코드 예제입니다. 앞에서 설명한 바인딩을 사용하면됩니다. 이상적으로 코드를 숨기지 않고 ViewModel 클래스로 리팩터링하는 것이 이상적입니다.

public partial class TimerView : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 
    private double _fontSize; 
    private readonly DispatcherTimer _timer; 

    public TimerView() 
    { 
     InitializeComponent(); 

     _timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(1) }; 
     _timer.Tick += delegate {/*calculate font size and set TimerFontSize*/}; 
     _timer.Start(); 
    } 

    public double TimerFontSize 
    { 
     get { return _fontSize; } 
     private set 
     { 
      _fontSize = value; 
      InvokePropertyChanged("TimerFontSize"); 
     } 
    } 

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

업데이트 2

그리고 바인딩 ValueConverter, 예컨대 :

을 사용하는 뷰 표현에서 모델 표현을 분리 :

FontSize="{Binding PercentageComplete, 
        Mode=OneWay, 
        Converter={StaticResource percentToFontSizeConverter}}" 

ValueConverter :

public class PercentToFontSizeValueConverter : IValueConverter 
{ 
    private static double _DpiX; 

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     double percent = (double)value; 
     double fontPointSize = (percent * 300); 
     double fontDpiSize = (fontPointSize * (DpiX/72d)); 
     return fontDpiSize; 
    } 

    private static double DpiX 
    { 
     get 
     { 
      if (_DpiX == 0) 
      { 
       Matrix m = PresentationSource. 
          FromVisual(Application.Current.MainWindow). 
          CompositionTarget. 
          TransformToDevice; 

       _DpiX = (m.M11 * 96d); 
      } 

      return _DpiX; 
     } 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 
} 

코드 숨김은 :

public partial class TimerView : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 
    private double _percent; 
    private readonly DispatcherTimer _timer; 

    public TimerView() 
    { 
     InitializeComponent(); 

     _timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(1) }; 
     _timer.Tick += delegate{/*Calulate perecent and set PercentageComplete */}; 
     _timer.Start(); 
    } 

    public double PercentageComplete 
    { 
     get { return _percent; } 
     private set 
     { 
      _percent = value; 
      InvokePropertyChanged("PercentageComplete"); 
     } 
    } 

    private void InvokePropertyChanged(string name) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(name)); 
     } 
    } 
} 
+0

답해 주셔서 감사합니다. 더 나은 것이 나타나지 않으면 내가 제안한대로 할 것입니다. 내 목표는 일반적으로 애니메이션과 스타일에서 시간을 변경하는 논리를 분리하는 것이 었습니다. 어쨌든, 나는 여전히 XAML에서 코드의 변수를 속성 값으로 사용하는 방법을 모른다. – Boris

+0

@ Borris xaml의 코드 숨김에서 속성을 사용하는 예제 코드로 답변을 업데이트했습니다. –

+0

@ 보리스 Font Point-to-DPI 크기 계산이 잘못되었습니다. 이제 코드가 업데이트되고 수정되었습니다. –

관련 문제