WPF: Как использовать переменную из кода в качестве значения свойства в XAML? - PullRequest
2 голосов
/ 29 декабря 2010

Я использую таймер обратного отсчета.У меня есть TextBlock, который показывает время, используя DispatcherTimer.

Я хотел бы создать анимацию для этого свойства TextBlock FontSize.Я хочу, чтобы его значение увеличилось до 300pt в момент, когда таймер показывает 9 вечера.Таким образом, он начинается с FontSize 8pt при каждом запуске приложения и продолжает увеличиваться, а когда в реальном времени достигает 9 вечера, FontSize должен быть 300pt.

Вот как я это изобразил: как только приложение запустится, оно рассчитает количество секунд, которое требуется с этого момента, чтобы добраться до 21:00;результат будет сохранен переменной timeToGetTo9pm.Проблема, с которой я сталкиваюсь, заключается в том, что когда я создаю анимацию в XAML, я не знаю, как установить timeToGetTo9pm для свойства animation Duration.

Есть идеи?Кроме того, если мой подход глуп или запутан, пожалуйста, не стесняйтесь рекомендовать лучший.Благодарю.

Тело делегата:

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

1 Ответ

3 голосов
/ 29 декабря 2010

Почему бы не иметь свойство TimerFontSize в ViewModel \ Code-Behind и привязать к нему TextBox FontSize.

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

По мере того как ваш таймер тикает, пересчитайте размер шрифта и установите свойство TimerFontSize. Если вы внедрили INotifyPropertyChanged для TimerFontSize, привязка 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();
    }
}

Code-Behind:

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));
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...