WPF(MVVM) UserControll. Как вернуть свойство из UserControll в ViewModel

Всем привет!

Цель - хочу написать UserControll светлофор. Что б прибиндить из ViewModel к нему 3 свойства. И если я нажму на одну из лампочек (зеленый , красный , желтый) изменялись эти свойства. Хай свойства называются FLAG1,FLAG2,FLAG3 типа bool. И при нажатии на лампочку , загорался свет и одно из свойств переходило в состояние true, а другие в false.

Или же что б огни саме переключались.

Пример - нажмимаю на центральну лампочку светлофора - цвет этой лампочки стал желтый и FLAG1 = false; FLAG2 = true; FLAG3 = false;


Ответы (1 шт):

Автор решения: Шимченко Максим

Вот код, сделайте лучше, так как он плохой. Если что время по простому методу обчисляю. Знаю что рендер будет задерживатся.

Фото каталога

App.xaml.cs

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;


using TrafficLight.ViewModel;
using TrafficLight.View;

namespace TrafficLight
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : Application
    {
        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);
            new MainWindow() { DataContext = new MainWindowViewModel() }.Show();
        }
    }
}

MainWindow.xaml

<Window x:Class="TrafficLight.View.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:TrafficLight.View"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800"
        xmlns:tr="clr-namespace:TrafficLight.UserControls">
    <Grid>
        <tr:Traffic Flag1="{Binding Flag1, Mode=TwoWay}" Flag2="{Binding Flag2, Mode=TwoWay}" Flag3="{Binding Flag3, Mode=TwoWay}"/>
    </Grid>
</Window>

MainWindow.xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace TrafficLight.View
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    }
}

MainWindowViewModel.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TrafficLight.ViewModel
{
    public class MainWindowViewModel : ViewModelBase
    {
        public MainWindowViewModel()
        {

        }

        private bool flag1 = false;
        public bool Flag1
        {
            get 
            { 
                return flag1; 
            }
            set 
            { 
                flag1 = value;
                Print();
                OnPropertyChange(nameof(Flag1)); 
            }
        }



        private bool flag2 = false;
        public bool Flag2
        {
            get
            {
                return flag2;
            }
            set
            {
                flag2 = value;
                Print();
                OnPropertyChange(nameof(Flag2));
            }
        }



        private bool flag3 = true;
        public bool Flag3
        {
            get
            {
                return flag3;
            }
            set
            {
                flag3 = value;
                Print();
                OnPropertyChange(nameof(Flag3));
            }
        }



        private void Print()
        {
            System.Diagnostics.Debug.WriteLine("----------------");
            System.Diagnostics.Debug.WriteLine("Flag1: " + Flag1);
            System.Diagnostics.Debug.WriteLine("Flag2: " + Flag2);
            System.Diagnostics.Debug.WriteLine("Flag3: " + Flag3);
            System.Diagnostics.Debug.WriteLine("----------------");
        }

    }
}

Traffic.xaml

<UserControl x:Class="TrafficLight.UserControls.Traffic"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:TrafficLight.UserControls"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>

        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>




        <Ellipse
             Width="200"
             Height="420"
             Fill="WhiteSmoke"
             Stroke="Silver"
             StrokeThickness=".5" Grid.RowSpan="3"/>



        <Ellipse
                 Width="100"
                 Height="100"
                 Fill="Gray"
                 Stroke="Silver"
                 StrokeThickness=".5"  x:Name="Green"/>
        
        <Ellipse Grid.Row="1"
                 Width="100"
                 Height="100"
                 Fill="Gray"
                 Stroke="Silver"
                 StrokeThickness=".5" x:Name="Yellow" />
        
        <Ellipse Grid.Row="2"
                 Width="100"
                 Height="100"
                 Fill="Gray"
                 Stroke="Silver"
                 StrokeThickness=".5" x:Name="Red" />

    </Grid>
</UserControl>

Traffic.xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;

namespace TrafficLight.UserControls
{
    /// <summary>
    /// Логика взаимодействия для Traffic.xaml
    /// </summary>
    public partial class Traffic : UserControl
    {


        public bool Flag1
        {
            get { return (bool)GetValue(Flag1Property); }
            set { SetValue(Flag1Property, value); }
        }

        public static readonly DependencyProperty Flag1Property =
            DependencyProperty.Register("Flag1", typeof(bool), typeof(Traffic), new PropertyMetadata(false));

        public bool Flag2
        {
            get { return (bool)GetValue(Flag2Property); }
            set { SetValue(Flag2Property, value); }
        }

        public static readonly DependencyProperty Flag2Property =
            DependencyProperty.Register("Flag2", typeof(bool), typeof(Traffic), new PropertyMetadata(false));


        public bool Flag3
        {
            get { return (bool)GetValue(Flag3Property); }
            set { SetValue(Flag3Property, value); }
        }

        public static readonly DependencyProperty Flag3Property =
            DependencyProperty.Register("Flag3", typeof(bool), typeof(Traffic), new PropertyMetadata(false));

       


        public Traffic()
        {

            InitializeComponent();

            int number = 0;

            if (Flag1 == true)
            {
                number = 1;
            }
            else if (Flag2 == true)
            {
                number = 2;
            }
            else
            {
                number = 3;
            }
            StartLight(number);
        }


        private void StartLight(int number)
        {
            DispatcherTimer dispatcherTimer = new DispatcherTimer();
            dispatcherTimer.Interval = TimeSpan.FromSeconds(1);
            dispatcherTimer.Tick += Tick;
            dispatcherTimer.Start();
        }


        public async void Tick(object sender, EventArgs e)
        {
            this.Dispatcher.Invoke(() =>
            {
                if (Flag1 == true)
                {
                    Flag1 = false;
                    Flag2 = true;
                    Flag3 = false;
                }
                else if (Flag2 == true)
                {
                    Flag1 = false;
                    Flag2 = false;
                    Flag3 = true;
                }
                else
                {
                    Flag1 = true;
                    Flag2 = false;
                    Flag3 = false;
                }


                SetColors();
            }


            );

        }


        private void SetColors()
        {
            if(Flag1 == true)
            {
                Green.Fill = Brushes.Green;
            }
            else
            {
                Green.Fill = Brushes.Gray;
            }




            if (Flag2 == true)
            {
                Yellow.Fill = Brushes.Yellow;
            }
            else
            {
                Yellow.Fill = Brushes.Gray;
            }




            if (Flag3 == true)
            {
                Red.Fill = Brushes.Red;
            }
            else
            {
                Red.Fill = Brushes.Gray;
            }
        }








    }
}

Результат

Результат

ViewModelBase.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TrafficLight.ViewModel
{
    public class ViewModelBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler? PropertyChanged;

        public void OnPropertyChange(string name = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }
    }
}

RelayCommand.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;

namespace TrafficLight.ViewModel
{
    public class RelayCommand : ICommand
    {
        private Action<object> execute;
        private Func<object, bool> canExecute;

        public event EventHandler CanExecuteChanged
        {
            add { 
                CommandManager.RequerySuggested += value; 
            }
            remove { 
                CommandManager.RequerySuggested -= value; 
            }
        }

        public RelayCommand(Action<object> execute, Func<object, bool> canExecute)
        {
            if (CanExecute == null)
                throw new ArgumentNullException("execute");
            this.execute = execute;
            this.canExecute = canExecute;
        }

        public bool CanExecute(object parameter)
        {
            return this.canExecute == null ? true: canExecute(parameter);
        }

        public void Execute(object parameter)
        {
            this.execute?.Invoke(parameter);
        }
    }

}
→ Ссылка