根据MainState枚举绑定SubState枚举

时间:2018-10-19 06:59:09

标签: c# wpf xaml data-binding

我试图基于主状态将标签值绑定到子状态枚举。每个Mainstate都有一个不同的子状态枚举,这就是为什么当mainstate更改时,我需要将标签重新绑定到不同的子状态枚举。但是我该怎么做呢?就是相应的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"

CALIBRATE中的主要状态和Calibrate的子状态为SUB_STATE_C1

2 个答案:

答案 0 :(得分:1)

按照步骤操作

  1. 在ViewModel中创建一个名为“ SubState”的字符串属性,并将其绑定到标签,如下所示,

      private string _subState;    
      public string SubState    
      {
         get { return _subState; }
         set { _subState = value; OnPropertyChanged(); }
      }
    
  2. 更新您的xaml以绑定到SubState字符串属性。

    <Label Content="{Binding SubState}" />
    
  3. 假定您有一个命令或一个事件用于选择更改事件,以检查STATE何时已更改,并在事件处理程序上,如下更新“ SubState”文本。

注意:-对于演示,我在代码隐藏中使用了绑定到List的组合框的事件处理程序

     <ComboBox ItemsSource="{Binding States}" Grid.Row="0"
             x:Name="CmbState" SelectionChanged="ComboBox_SelectionChanged">
     </ComboBox>
  1. 这是我完整的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>
    
  2. 代码隐藏的SelectionChanged事件

           private void ComboBox_SelectionChanged(object sender,
           SelectionChangedEventArgs e)
          {
              var cmbSender = sender as ComboBox;
              var state = (Motor.STATE) cmbSender.SelectedItem;
              mainVm.SetState(state);
          }
    
  3. 这是我的ViewModel的SetState方法

          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();
              }
          }
    
  4. 声明一个列表并绑定到您的组合框,并如下所示在ViewModel构造函数中初始化“状态”列表对象,

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

注意:MainVM是我的ViewModel,我个人认为Motor类应该只包含数据成员,而不包含任何属性更改事件或与VM相关的其他事情。因此,我已经将某些项目从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对象,并且将故事的其余部分创建为上面提到的。

希望我已明确表示,如果您还有其他疑问,请不要犹豫,再次询问。

答案 1 :(得分:1)

就像@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}" />

并且某些状态已更改时,您必须通知UI。为此,只需添加 像这样OnPropertyChanged("CurrentStateText");到达所有州Setter

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

注意:我手边没有IDE,因此代码中可能存在语法/拼写错误。