Конвертер не вызывается после выполнения команды

Эта кнопка должна переключаться между доступным списком цветов и соответствующим образом изменять цвет фона.

Изначально у меня была эта часть кода модели представления в одной большой / основной модели представления, но я решил разделить ее, чтобы каждый из моих пользовательских элементов управления имел свою собственную модель представления. Я попытался установить точку останова, в которой выполняется метод 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>

Зачем нужны объекты ViewModel? <cam:CameraPropertiesViewModel x:Key = "CPVM" /> и <local:CameraPropertiesViewModel x:Key = "CPVM" />?

user1672994 02.05.2018 19:17

Что такое MainView и нужно ли нам видеть исходный код CameraPropertiesView? Как установить ViewModels / DataContext?

V.Leon 02.05.2018 19:29

@ user1672994 это потому, что свойство привязки "State" находится в этой модели представления, и именно так я создаю ссылку на него.

nwahs 02.05.2018 19:56

@ V.Leon MainView - это, по сути, класс представления, который содержит пространства имен для дочерних классов представления. Я считаю, что модели представления / datacontext настроены так, как показано в файле MainWindow.xaml, который показан выше.

nwahs 02.05.2018 19:56

@nwahs - мой вопрос заключался в том, почему два разных объекта имеют одну и ту же модель представления?

user1672994 02.05.2018 19:57

@ user1672994, один находится в MainView.xaml, а другой - в CameraPropertiesView.xaml. Я предполагаю, что мне следует оставить только один в MainView и каким-то образом использовать его в CameraPropertiesView?

nwahs 02.05.2018 20:01

Да, поскольку ваш MainViewModel уже работает на CurrentViewModel, а DataTemplate уже определен, поэтому вам не нужна ViewModel дочернего представления.

user1672994 02.05.2018 20:07

@ user1672994 Но дело в том, что если я не создам пространство имен и не буду ссылаться на него в CameraPropertiesView.xaml, он не сможет найти соответствующую команду, к которой привязана кнопка, которая находится в CameraPropertiesViewModel.cs

nwahs 02.05.2018 20:18

@nwahs - WPF автоматически устанавливает DataContext элемента контейнера для соответствующего экземпляра элемента, чтобы его можно было унаследовать. Удалите его и попробуйте, ваша привязка должна автоматически наследоваться от верхнего объекта ViewModel.

user1672994 02.05.2018 20:24
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
9
38
1

Ответы 1

Мне удалось воспроизвести вашу проблему, удалив неважные стили, модели просмотра и т. д.

Вам просто не хватает атрибута 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 кнопку из исходной модели представления и закомментировал части в оригинале. читает значение состояния из этой новой модели представления.

nwahs 02.05.2018 20:12

Другие вопросы по теме