Эта кнопка должна переключаться между доступным списком цветов и соответствующим образом изменять цвет фона.
Изначально у меня была эта часть кода модели представления в одной большой / основной модели представления, но я решил разделить ее, чтобы каждый из моих пользовательских элементов управления имел свою собственную модель представления. Я попытался установить точку останова, в которой выполняется метод OnChangeColor (), и я вижу, что состояние действительно меняется, но, похоже, это изменение не сохраняется в преобразователе, который, следовательно, не обновляет цвет фона пользовательского интерфейса вообще.
Я разместил код ниже, в который я внес изменения и в настоящее время работаю, чтобы попытаться выяснить, в чем проблема.
MainWindow
<Window.DataContext>
<local:MainWindowViewModel />
</Window.DataContext>
<Window.Resources>
<DataTemplate DataType = "{x:Type local:CameraListViewModel}">
<local:MainView />
</DataTemplate>
<DataTemplate DataType = "{x:Type rep:ReportViewModel}">
<rep:ReportView />
</DataTemplate>
<DataTemplate DataType = "{x:Type cam:CameraMonitorViewModel}">
<cam:CameraMonitorView />
</DataTemplate>
<DataTemplate DataType = "{x:Type cam:CameraPropertiesViewModel}">
<cam:CameraPropertiesView />
</DataTemplate>
</Window.Resources>
<Grid>
<ContentControl Content = "{Binding CurrentViewModel}" />
</Grid>
Просмотреть модель:
public class CameraPropertiesViewModel : ViewModelBase
{
/// <summary>
/// The current state of the background color
/// </summary>
private States _state;
//Delegate commands for the UI
private DelegateCommand _changeColorCommand;
public ICommand ChangeColorCommand
{
get
{
if (_changeColorCommand == null)
{
_changeColorCommand = new DelegateCommand(OnChangeColor);
}
return _changeColorCommand;
}
}
//All possible background colors
public enum States
{
GREEN,
YELLOW,
RED
}
//Gets or sets the background color
public States State
{
get
{
return _state;
}
set
{
SetProperty(ref _state, value);
}
}
//Cycle through different colors
private void OnChangeColor()
{
if (State == States.GREEN)
State = States.RED;
else if (State == States.RED)
State = States.YELLOW;
else if (State == States.YELLOW)
State = States.GREEN;
}
}
Конвертер:
[ValueConversion(typeof(CameraPropertiesViewModel.States), typeof(Brush))]
public class EnumToColorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
CameraPropertiesViewModel.States state = (CameraPropertiesViewModel.States)value;
switch (state)
{
case CameraPropertiesViewModel.States.GREEN:
return new SolidColorBrush(Colors.Green);
case CameraPropertiesViewModel.States.YELLOW:
return new SolidColorBrush(Colors.Yellow);
case CameraPropertiesViewModel.States.RED:
return new SolidColorBrush(Colors.Red);
}
return new SolidColorBrush(Colors.LightGray);
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return null;
}
}
MainView
<UserControl.Resources>
<conv:EnumToColorConverter x:Key = "enumToColorConvert"/>
<cam:CameraPropertiesViewModel x:Key = "CPVM" />
</UserControl.Resources>
<Grid Background = "{Binding Path=State, Source = {StaticResource CPVM}, Converter = {StaticResource enumToColorConvert}}">
<Grid.RowDefinitions>
<RowDefinition Height = "Auto" />
<RowDefinition />
<RowDefinition Height = "Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width = "Auto"/>
</Grid.ColumnDefinitions>
<cam:CamerasListView />
<cam:CameraPropertiesView Grid.Column = "1"/>
<cam:CameraMonitorView Grid.Row = "1"
Grid.ColumnSpan = "2" />
<cam:CameraFunctionView Grid.Row = "2"
Grid.ColumnSpan = "2"/>
</Grid>
Ресурсы:
<local:CameraPropertiesViewModel x:Key = "CPVM" />
Кнопка
<Button Style = "{StaticResource circleButton}"
Command = "{Binding ChangeColorCommand, Source = {StaticResource CPVM}}"
Content = "Change Theme"
Width = "100"
HorizontalAlignment = "Center"
VerticalAlignment = "Center"
Grid.Column = "2"
Grid.Row = "2"/>
CameraPropertiesView.xaml
<UserControl.Resources>
<local:CameraPropertiesViewModel x:Key = "CPVM" />
<Style TargetType = "{x:Type Button}" x:Key = "circleButton">
<Setter Property = "Template">
<Setter.Value>
<ControlTemplate>
<Grid>
<Viewbox>
<Canvas Width = "50" Height = "50">
<Ellipse Fill = "{TemplateBinding Control.Background}" Width = "50" Height = "50"/>
</Canvas>
</Viewbox>
<ContentPresenter VerticalAlignment = "Center" HorizontalAlignment = "Center" Content = "{TemplateBinding Button.Content}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Grid>
<GroupBox Header = "Camera Details"
Height = "130"
Width = "386"
HorizontalAlignment = "Right"
VerticalAlignment = "Top"
Margin = "10">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width = "Auto" />
<ColumnDefinition />
<ColumnDefinition Width = "120" />
</Grid.ColumnDefinitions>
<Label Height = "25"
Width = "70"
Content = "Name"
HorizontalAlignment = "Center"
VerticalAlignment = "Center"
HorizontalContentAlignment = "Right" />
<TextBox Text = "{Binding ConnectedCamera.Name}"
HorizontalAlignment = "Center"
VerticalAlignment = "Center"
Height = "23"
Width = "160"
Grid.Column = "1"
IsReadOnly = "True" />
<Label Height = "25"
Width = "70"
Content = "Model"
HorizontalAlignment = "Center"
VerticalAlignment = "Center"
Grid.Row = "1"
HorizontalContentAlignment = "Right" />
<TextBox Text = "{Binding ConnectedCamera.Model}"
HorizontalAlignment = "Center"
VerticalAlignment = "Center"
Height = "23"
Width = "160"
IsReadOnly = "True"
Grid.Column = "1"
Grid.Row = "1" />
<Label Height = "25"
Width = "70"
Content = "Ip Address"
HorizontalAlignment = "Center"
VerticalAlignment = "Center"
Grid.Row = "2"
HorizontalContentAlignment = "Right" />
<TextBox Text = "{Binding ConnectedCamera.IpAddress}"
HorizontalAlignment = "Center"
VerticalAlignment = "Center"
Height = "23"
Width = "160"
IsReadOnly = "True"
Grid.Column = "1"
Grid.Row = "2" />
<Button Command = "{Binding GenerateReportCommand}"
Content = "Generate Report"
Width = "100"
HorizontalAlignment = "Center"
VerticalAlignment = "Center"
Grid.Column = "2" />
<Button Command = "{Binding ArchiveReportCommand}"
Content = "Archive Report"
Width = "100"
HorizontalAlignment = "Center"
VerticalAlignment = "Center"
Grid.Column = "2"
Grid.Row = "1"/>
<Button Style = "{StaticResource circleButton}"
Command = "{Binding ChangeColorCommand, Source = {StaticResource CPVM}}"
Content = "Change Theme"
Width = "100"
HorizontalAlignment = "Center"
VerticalAlignment = "Center"
Grid.Column = "2"
Grid.Row = "2"/>
</Grid>
</GroupBox>
</Grid>
Что такое MainView и нужно ли нам видеть исходный код CameraPropertiesView? Как установить ViewModels / DataContext?
@ user1672994 это потому, что свойство привязки "State" находится в этой модели представления, и именно так я создаю ссылку на него.
@ V.Leon MainView - это, по сути, класс представления, который содержит пространства имен для дочерних классов представления. Я считаю, что модели представления / datacontext настроены так, как показано в файле MainWindow.xaml, который показан выше.
@nwahs - мой вопрос заключался в том, почему два разных объекта имеют одну и ту же модель представления?
@ user1672994, один находится в MainView.xaml, а другой - в CameraPropertiesView.xaml. Я предполагаю, что мне следует оставить только один в MainView и каким-то образом использовать его в CameraPropertiesView?
Да, поскольку ваш MainViewModel уже работает на CurrentViewModel, а DataTemplate уже определен, поэтому вам не нужна ViewModel дочернего представления.
@ user1672994 Но дело в том, что если я не создам пространство имен и не буду ссылаться на него в CameraPropertiesView.xaml, он не сможет найти соответствующую команду, к которой привязана кнопка, которая находится в CameraPropertiesViewModel.cs
@nwahs - WPF автоматически устанавливает DataContext элемента контейнера для соответствующего экземпляра элемента, чтобы его можно было унаследовать. Удалите его и попробуйте, ваша привязка должна автоматически наследоваться от верхнего объекта ViewModel.





Мне удалось воспроизвести вашу проблему, удалив неважные стили, модели просмотра и т. д.
Вам просто не хватает атрибута Source в привязке к сетке. Обратите внимание на то, что это кнопка, но не сетка.
<Grid Background = "{Binding Path=State,
Converter = {StaticResource enumToColorConvert}}">
Должно быть:
<Grid Background = "{Binding Path=State,
Converter = {StaticResource enumToColorConvert},
Source = {StaticResource CPVM}}">
Извините, я забыл включить эту фиксированную часть, но я уже пробовал это, и она все еще не работает :( В основном это началось с переменной State, изначально находящейся в этой одной большой модели представления под названием CameraListViewModel, а затем я решил разделить часть эту логику в свой собственный пользовательский элемент управления и модель представления (CameraPropertyViews & CameraPropertiesViewModel). Теперь я скопировал и вставил связанный код на эту 1 кнопку из исходной модели представления и закомментировал части в оригинале. читает значение состояния из этой новой модели представления.
Зачем нужны объекты ViewModel?
<cam:CameraPropertiesViewModel x:Key = "CPVM" />и<local:CameraPropertiesViewModel x:Key = "CPVM" />?