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

