Связывание перечислений SubState на основе перечисления MainState - PullRequest
0 голосов
/ 19 октября 2018

Я пытаюсь привязать значение метки к перечислению подсостояния на основе основного состояния.Каждое основное состояние имеет разные перечисления подсостояний, поэтому при изменении основного состояния мне нужно привязать метку к другому перечислению подсостояний.Но как я могу это сделать, это соответствующий код XAML.

Это класс, содержащий 3 перечисления состояния (1 основное состояние и 2 подсостояния)

public class Motor : ObservableObject
{
    public enum STATE
    {
        IDLE,
        CALIBRATE,
        GO_HOME
    }

    public enum CALIBRATE_TRACK
    {
        SUB_STATE_C1,
        SUB_STATE_C2,
        SUB_STATE_C3,
        SUB_STATE_C4,
    }

    public enum HOMING
    {
        SUB_STATE_H1,
        SUB_STATE_H2,
        SUB_STATE_H3,
    }

    private STATE _currentState = STATE.IDLE;
    public STATE CurrentState
    {
        get { return _currentState; }
        set { _currentState = value; OnPropertyChanged("CurrentState"); }
    }

    private CALIBRATE_TRACK _calibrateTrackState = CALIBRATE_TRACK.SUB_STATE_C1;
    public CALIBRATE_TRACK CalibrateTrackState
    {
        get { return _calibrateTrackState; }
        set { _calibrateTrackState = value; OnPropertyChanged("CalibrateTrackState"); }
    }


    private HOMING _homeingState = HOMING.SUB_STATE_H1;
    public HOMING HomeingState
    {
        get { return _homeingState; }
        set { _homeingState = value; OnPropertyChanged("HomeingState"); }
    }
}

Так что, когда CurrentState дляпример меняется на CALIBRATE, затем я хочу привязать к элементу подсостояния CalibrateTrackState, а когда CurrentState меняется на GO_HOME, тогда я хочу привязать к элементу подсостояния HomeingState

Это XAMLкод, который у меня пока есть:

<Label>
    <Label.Content>
        <TextBlock>
            <TextBlock.Text>
                <MultiBinding StringFormat="{}{0} - {1}">
                    <Binding Path="motor.CurrentState"/>
                    <Binding Path="motor.xxx"/>
                </MultiBinding>
            </TextBlock.Text>
        </TextBlock>
    </Label.Content>
</Label>

Так что привязка CurrentState не проблема.Но я не знаю, как связать подсостояние.В приведенном выше примере я добавил местозаполнитель для местоположения подсостояния под названием motor.xxx.

Тогда полученный результат должен быть примерно таким:

"CALIBRATE - SUB_STATE_C1"

, когда mainstate в CALIBRATEа подсостояние калибровки составляет SUB_STATE_C1

Ответы [ 2 ]

0 голосов
/ 19 октября 2018

Как @ASh уже сказал в комментариях, я предлагаю вам создать Property, который форматирует весь штат.

Свойство:

public string CurrentStateText
{
    get
    {
        if (CurrentState.Equals(STATE.IDLE))
            return CurrentState;

        else if (CurrentState.Equals(STATE.CALIBRATE))
            return String.Format("{0} - {1}", CurrentState, CalibrateTrackState);

        else if (CurrentState.Equals(STATE.GO_HOME))
            return String.Format("{0} - {1}", CurrentState, HomeingState);

        else return "Invalid STATE!";
    }
}

Связывание

<Label Content="{Binding CurrentStateText}" />

И вы должны уведомить пользовательский интерфейс, когда некоторые штаты изменились.Для этого просто добавьте OnPropertyChanged("CurrentStateText"); ко всем состояниям Setter следующим образом

set { _currentState = value; OnPropertyChanged("CurrentState"); OnPropertyChanged("CurrentStateText"); }
set { _calibrateTrackState = value; OnPropertyChanged("CalibrateTrackState"); OnPropertyChanged("CurrentStateText"); }
etc.

Примечание: у меня нет моей IDE под рукой, поэтому в коде могут быть ошибки синтаксиса / орфографии.

0 голосов
/ 19 октября 2018

Выполните шаги,

  1. Создайте строковое свойство с именем «SubState» в вашей модели представления и привяжите его к метке, как показано ниже,

      private string _subState;    
      public string SubState    
      {
         get { return _subState; }
         set { _subState = value; OnPropertyChanged(); }
      }
    
  2. Обновите свой xaml для привязки к свойству строки SubState.

    <Label Content="{Binding SubState}" />
    
  3. Предполагается, что у вас есть команда или событие для события изменения выбора, чтобы проверить, когда изменилось STATE и наобработчик событий, обновите текст «SubState», как показано ниже.

Примечание: - Для демонстрации я использую обработчик событий в коде для комбинированного списка, привязанного к списку

     <ComboBox ItemsSource="{Binding States}" Grid.Row="0"
             x:Name="CmbState" SelectionChanged="ComboBox_SelectionChanged">
     </ComboBox>

Вот мой полный xaml

    <Grid>
      <Grid.RowDefinitions>
          <RowDefinition Height="Auto" />
          <RowDefinition Height="Auto" />
      </Grid.RowDefinitions>

      <ComboBox ItemsSource="{Binding States}" Grid.Row="0" x:Name="CmbState" SelectionChanged="ComboBox_SelectionChanged">
      </ComboBox>
      <Label Content="{Binding SubState}" Grid.Row="1" />
    </Grid>

Событие SelectionChanged при выделении кода

       private void ComboBox_SelectionChanged(object sender,
       SelectionChangedEventArgs e)
      {
          var cmbSender = sender as ComboBox;
          var state = (Motor.STATE) cmbSender.SelectedItem;
          mainVm.SetState(state);
      }

ВотМетод SetState моей ViewModel

      public void SetState(object selectedState)
      {
          if(selectedState.ToString() == STATE.IDLE.ToString())
          {
              SubState = CurrentState.ToString();
          }
          else if(selectedState.ToString() == STATE.CALIBRATE.ToString())
          {
              SubState = CalibrateTrackState.ToString();
          }
          else
          {
              SubState = HomeingState.ToString();
          }
      }

Объявление списка и привязка к вашему комбинированному списку и инициализация объекта списка состояний в конструкторе ViewModel, как показано ниже,

          public List<STATE> States { get; set; }
          States = new List<STATE>
          {
              STATE.IDLE,
              STATE.CALIBRATE,
              STATE.GO_HOME
          };

Примечание: - MainVM - это моя ViewModel, и я лично считаю, что класс Motor должен содержать только элементы данных, а не какие-либо события, изменяющие свойства, или что-то еще, связанное с ВМ, которое необходимо сделать.Итак, я переместил некоторые элементы из класса Motor в свою ViewModel.

См. Мою полную ViewModel

  class MainVM : INotifyPropertyChanged
      {

          public List<STATE> States { get; set; }

          private string _subState;
          public string SubState
          {
              get { return _subState; }
              set { _subState = value; OnPropertyChanged(); }
          }

          public MainVM()
          {
              States = new List<STATE>
              {
                  STATE.IDLE,
                  STATE.CALIBRATE,
                  STATE.GO_HOME
              };

              SubState = CurrentState.ToString();
          }



          public void SetState(object selectedState)
          {
              if(selectedState.ToString() == STATE.IDLE.ToString())
              {
                  SubState = CurrentState.ToString();
              }
              else if(selectedState.ToString() == STATE.CALIBRATE.ToString())
              {
                  SubState = CalibrateTrackState.ToString();
              }
              else
              {
                  SubState = HomeingState.ToString();
              }
          }

          private STATE _currentState = STATE.IDLE;
          public STATE CurrentState
          {
              get { return _currentState; }
             set { _currentState = value; OnPropertyChanged("CurrentState"); }
         }

         private CALIBRATE_TRACK _calibrateTrackState = CALIBRATE_TRACK.SUB_STATE_C1;
          public CALIBRATE_TRACK CalibrateTrackState
          {
              get { return _calibrateTrackState; }
              set { _calibrateTrackState = value; OnPropertyChanged("CalibrateTrackState"); }
          }

          private HOMING _homeingState = HOMING.SUB_STATE_H1;
          public HOMING HomeingState
          {
              get { return _homeingState; }
              set { _homeingState = value; OnPropertyChanged("HomeingState"); }
          }

          protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
          {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
          }

          public event PropertyChangedEventHandler PropertyChanged;
      }

Примечание: - Я вставил код, который вам может не потребоваться полностью, так как яне знаю, как вы проверяете изменение STATE, поэтому я предположил привязку комбо-бокса к вашему объекту ViewModel и создал остальную часть истории, как указано выше.

Надеюсь, я дал понять, что если у вас естьлюбые другие сомнения, не стесняйтесь спрашивать снова.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...