我试图基于主状态将标签值绑定到子状态枚举。每个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
答案 0 :(得分:1)
按照步骤操作
在ViewModel中创建一个名为“ SubState”的字符串属性,并将其绑定到标签,如下所示,
private string _subState;
public string SubState
{
get { return _subState; }
set { _subState = value; OnPropertyChanged(); }
}
更新您的xaml以绑定到SubState字符串属性。
<Label Content="{Binding SubState}" />
假定您有一个命令或一个事件用于选择更改事件,以检查STATE何时已更改,并在事件处理程序上,如下更新“ SubState”文本。
注意:-对于演示,我在代码隐藏中使用了绑定到List的组合框的事件处理程序
<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);
}
这是我的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();
}
}
声明一个列表并绑定到您的组合框,并如下所示在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,因此代码中可能存在语法/拼写错误。