Member 13048543 Ответов: 1

Как отобразить таймер в текстовом поле?


Привет,

Я новичок в C#, у меня мало сомнений относительно MVVM. Когда использовать IVauleConverter и концепцию привязки? Чтобы понять концепцию, я написал небольшой демо-проект.
На самом деле я пытаюсь реализовать небольшой проект ,где у меня есть имя,фамилия, полное имя, таймер и Эллипс.Текстовое поле таймера должно отображать время, когда возникает событие обработчика времени, и цвет эллипса должен измениться. Я хочу написать код для пользовательского интерфейса отдельно, и логика должна быть другой.В приведенном ниже коде он не отображает время в текстовом поле таймера.

Что я уже пробовал:

private DispatcherTimer atimer;
        public Person personobj { get; set; }

       public MainWindow()
        {
            InitializeComponent();
            personobj = new Person();
            personobj.firstName = "hello";
            personobj.lastName= "";
           
            this.DataContext = personobj;
            // aTimer = new System.Timers.Timer(2000);
            // aTimer.Elapsed += new ElapsedEventHandler(OnTimeEvent);
            // aTimer.Enabled = true;
         //   atimer = new DispatcherTimer();
           // atimer.Interval = TimeSpan.FromMilliseconds(5000);
            //atimer.Tick += new EventHandler(OnTimeEvent);
            //atimer.Start();

        }

        /*private void OnTimeEvent(object sender, EventArgs e)
        {
            //TimerCount.Text = DateTime.Now.ToString("hh:mm:ss");
           // throw new NotImplementedException();
        }*/
    }

    public class Person : INotifyPropertyChanged
    {
        
        /// <summary>
        /// 
        /// 
        public String firstName;
        public String lastName;
        public String fullName="";
        private Boolean colorchange=false;
        private String timeIndicator;
        private DispatcherTimer timeCount;
        public Person()
        {
            timeCount = new DispatcherTimer();
            timeCount.Tick += new EventHandler(Timer_Tick);
            timeCount.Interval = TimeSpan.FromMilliseconds(5000);
            timeCount.Start();

        }
        public String FirstName
        {
            get
            {
                return firstName;
            }

            set
            {
                if (firstName != value)
                {
                    firstName = value;
                    OnPropertyChanged("FirstName");
                    OnPropertyChanged("FullName");
                }
            }
        }

        public String LastName
        {
            get
            {
                return lastName;
            }

            set
            {
                if (lastName != value)
                {
                    lastName = value;
                    OnPropertyChanged("LastName");
                    OnPropertyChanged("FullName");
                }
            }
        }

        public String FullName
        {
            get
            {
                //  Debug.WriteLine(fullName);
                return this.fullName = firstName + " " + lastName;

            }

            set
            {
                this.fullName = value;
                OnPropertyChanged("FullName");
                /*if (fullName != "")
                  {
                      colorchange = false;
                  }
                  else
                  {
                      colorchange = true;
                  }*/



                  }
            }


        public Boolean Colorchange
        {
            get
            {
                return colorchange;
            }

            set
            {
                colorchange = value;
                OnPropertyChanged("Colorchange");
            }
        }

        public string TimeIndicator
        {
            get
            {
                return timeIndicator;
            }

            set
            { 
                timeIndicator = value;
               if (timeIndicator != null)
                  {
                      colorchange = true;
                  }
                  else
                  {
                      colorchange = false;
                  }

                OnPropertyChanged("TimeIndicator");
            }
        }
      

        private void Timer_Tick(object sender, EventArgs e)
        {
            TimeIndicator = DateTime.UtcNow.ToString("hh:mm:ss");
        //    OnPropertyChanged("TimeIndicator");
        }
      //  public delegate PropertyChangedEventHandler(string property);
        public event PropertyChangedEventHandler PropertyChanged;

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


    }
   // [ValueConversion(typeof(Person), typeof(Brush))]
    public class ColorChange : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
         //  Boolean BooleanValue = (Boolean)value;
         
            if (value.ToString()!= null)
            {

                return value.ToString();

            }
            else
            {
                return (object)Brushes.Green;
            }
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
           if (value is bool)
            {
                if ((bool)value == true)
                    return new SolidColorBrush(Colors.Green);
                else
                    return new SolidColorBrush(Colors.Red);
            }
            return null;
        }
    }
}


<window.resources>
        <local:ColorChange x:Key="ColorChange"/>
    
    <grid>
        
        <TextBox  Text="{Binding Path=FirstName, Mode=TwoWay}" Margin="145,20,187,264" />

        
        <TextBox  Text="{Binding  Path=LastName, Mode=TwoWay}" Margin="145,75,187,209" />
        
        <TextBox Name="fulltxtname" Text="{Binding Path=FullName, Mode=TwoWay}"  Margin="145,125,187,159"/>
      
        
        <TextBox Name ="TimerCount" Text="{Binding Path=timeIndicator,Mode=TwoWay }" Margin="75,200,297,89"/>
        <Ellipse Fill="{Binding ElementName=TimerCount, Converter={StaticResource ColorChange}}" HorizontalAlignment="Left" Height="35" Margin="260,195,0,0" Stroke="Black" VerticalAlignment="Top" Width="40"/>

[no name]

Вероятно, потому, что вы привязываетесь к timeIndicator, но фактическое имя свойства-TimeIndicator. Те сообщения об ошибках привязки, которые вы видите в окне вывода, действительно пытаются Вам что-то сказать.

Member 13048543

Я исправил это, но я получаю en error ' DynamicValueConverter 'failed to convert value' System.Окна.Управления.TextBox'(Тип String).

[no name]

Это потому, что вы пытаетесь преобразовать систему.Окна.Управления.Управление текстовым полем в вашем конвертере точно так же, как вы ему сказали.

Member 13048543

Большое спасибо. Я добавил конвертер={StaticResource ColorChange} в текстовое поле таймера, после чего он показывает время.Но мое требование заключается в том, что всякий раз, когда возникает событие таймера, цвет эллипса должен меняться.Пожалуйста, не могли бы вы дать мне какое-нибудь предложение?

[no name]

Поэтому в вашем событии таймера измените цвет и уведомите пользовательский интерфейс о том, что произошло изменение. подсказка: именно это и делает OnNotifyPropertyChanged.

Member 13048543

Я ничего не понимал.Не могли бы вы объяснить немного подробнее?

[no name]

Ваш код должен делать это сейчас. Но я не запускаю ваш код, поэтому не вижу того, что вы видите на своем экране. Но ваше требование не имеет смысла. В соответствии с вашим кодом Colorchange всегда будет истинным на ТИКе времени, так что ваш цвет на самом деле не меняется.

1 Ответов

Рейтинг:
7

Graeme_Grant

Вот демонстрация того, как его настроить (да, я не использую таймер, но применяется тот же принцип):

Настройка базы уведомлений


Инкапсулируйте общий код.
using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace WpfBindingEvents
{
    public abstract class ObservableObject : INotifyPropertyChanged
    {
        public void Notify([CallerMemberName] string caller = "")
        {
            PropertyChanged?.Invoke(this,
                new PropertyChangedEventArgs(caller));

        }
        public event PropertyChangedEventHandler PropertyChanged;
    }
}

Модель


namespace WpfBindingEvents
{
    public class Person: ObservableObject
    {
        private string firstName;
        public string FirstName
        {
            get { return firstName; }
            set
            {
                firstName = value;
                Notify();
                SetFullName();
            }
        }

        private string lastName;
        public string LastName
        {
            get { return lastName; }
            set
            {
                lastName = value;
                Notify();
                SetFullName();
            }
        }

        private string fullName;
        public string FullName
        {
            get { return fullName; }
            private set
            {
                fullName = value;
                Notify();
            }
        }

        private void SetFullName()
        {
            FullName = firstName + " " + lastName;
        }
    }
}

модель представления


namespace WpfBindingEvents
{
    public class MainViewModel : ObservableObject
    {

        public MainViewModel()
        {
            Model.PropertyChanged += ModelPropertyChanged;
        }

        private void ModelPropertyChanged(object sender, 
                                          PropertyChangedEventArgs e)
        {
            HasFullName = !string.IsNullOrEmpty(Model.FullName);
        }

        public Person Model { get; } = new Person();

        private bool hasFullName;
        public bool HasFullName
        {
            get { return hasFullName; }
            set
            {
                hasFullName = value;
                Notify();
            }
        }
    }
}

ValueConverter


using System;
using System.Globalization;
using System.Windows.Data;
using System.Windows.Media;

namespace WpfBindingEvents
{
    public class ValidationColorConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return new SolidColorBrush((bool)value ? Colors.Green : Colors.Red);
        }

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

страница XAML


<Window x:Class="WpfBindingEvents.MainWindow"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

        xmlns:local="clr-namespace:WpfBindingEvents"

        mc:Ignorable="d"

        Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <local:MainViewModel/>
    </Window.DataContext>
    <Window.Resources>
        <local:ValidationColorConverter x:Key="ValidationColorConverter"/>
    </Window.Resources>
    <Grid HorizontalAlignment="Center" VerticalAlignment="Center">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="Auto"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <TextBlock Text="First Name:" Margin="10 5"/>
        <TextBox Text="{Binding Model.FirstName, Mode=TwoWay, 
                                UpdateSourceTrigger=PropertyChanged}" 

                 Grid.Column="1" 

                 Width="200" VerticalAlignment="Center"/>

        <TextBlock Text="Last Name:" Grid.Row="1" Margin="10 5"/>
        <TextBox Text="{Binding Model.LastName, Mode=TwoWay, 
                                UpdateSourceTrigger=PropertyChanged}" 

                 Grid.Row="1" Grid.Column="1" 

                 Width="200" VerticalAlignment="Center"/>

        <TextBlock Text="Full Name:" Grid.Row="2" Margin="10 0"

                   VerticalAlignment="Center"/>
        <Border BorderThickness="1" 

                BorderBrush="{Binding HasFullName, 
                                      Converter={StaticResource ValidationColorConverter}}" 

                Margin="0 5" Grid.Row="2" Grid.Column="1"

                HorizontalAlignment="Stretch">
            <TextBlock Text="{Binding Model.FullName}" Grid.Row="1" Margin="5"/>
        </Border>
    </Grid>
</Window>