2017-02-23 57 views
0

我正在開發一個使用C#/ WPF/MVVM的小實用程序,它允許設置我們用於測試的控制器的輸入狀態。我正在開發的應用程序與硬件/我們的Web服務通信到硬件之間的通信只是一種方式,這意味着應用程序將只能在設置的輸入狀態,而不是獲取的狀態。綁定單選按鈕IsChecked到對象的當前元素狀態數組

另一點需要注意的是,我們的解決方案的其他部分已經爲此定義了一些類型,這些都是在F#中。要做我的應用程序,我正在使用C#。所以我做了一個Unit類來環繞F#中定義的LocalControllerTypes.LocalController類型,其中包含大量所需的信息。

爲了做到這一點,我有一個enum列舉InputState可能(目前有ActiveNormal,但該列表可能會隨時間增長)。此外,每種單元類型上的輸入數量都不相同(有些有2個,有些有4個,有些有更多),所以我在選定單元的Inputs數組上綁定了一個ItemControl,不幸的是,它只包含輸入的名稱我必須展示。該單元有2個與其輸入相關的其他屬性,InputWriters,它是一種用於將命令發送到與該硬件通信的硬件/網絡服務的類型的數組,InputStates,其爲InputState的數組它的每個輸入都與應用程序中最後一次設置的一樣(因爲我們無法從硬件中獲取狀態)。現在

我想單選按鈕的IsChecked屬性綁定(這是我定義爲ItemsControlItemTemplate)至目前SelectedUnitInputState(在我的視圖模型)。 我遇到的問題是,是因爲我想知道單選按鈕是SelectedUnitInputs數組的索引號,以便獲得SelectedUnit的的InputStates屬性的相同索引處的項目。

有什麼辦法可以達到這個目的嗎?

MainWindow.xaml:

  ... 
      <ItemsControl Grid.Row="1" ItemsSource="{Binding SelectedUnit.LocalControllerInfo.Inputs}"> 
       <ItemsControl.ItemTemplate> 
        <DataTemplate> 
         <StackPanel Orientation="Horizontal"> 
          <TextBlock Margin="10" FontSize="15" Style="{StaticResource TextBlockNormalBase}" Text="{Binding InputName}"/> 
          <StackPanel Orientation="Horizontal"> 
           <RadioButton Margin="10" Foreground="White" Content="Normal" 
              IsChecked="{Binding Path=?, 
                   Converter={StaticResource inputToBoolConverter}, 
                   ConverterParameter=?}"/> 
           <RadioButton Margin="10" Foreground="White" Content="Active" 
              IsChecked="{Binding Path=?, 
                   Converter={StaticResource inputToBoolConverter}, 
                   ConverterParameter=?}"/> 
          </StackPanel> 
         </StackPanel> 
        </DataTemplate> 
       </ItemsControl.ItemTemplate> 
      </ItemsControl> 
      ... 

Unit.cs:

public class Unit : BindableObject 
{ 
    public enum InputState 
    { 
     Normal, 
     Active 
    } 

    private LocalControllerTypes.LocalController _localControllerInfo; 
    private LocalControllerTypes.ArduinoInjector[] _arduinoInjector; 
    private WebWriter.WebWriter[] _inputWriters; 
    private SNMPNetworkSwitchConnection.SNMPNetworkSwitchConnection _networkSwitchConnection; 
    private InputState[] _inputStates; 
    private bool _isUnitConnected; 

    public Unit(LocalControllerTypes.LocalController localControllerInfo, 
     LocalControllerTypes.ArduinoInjector[] arduinoInjector, 
     WebWriter.WebWriter[] inputWriters, 
     SNMPNetworkSwitchConnection.SNMPNetworkSwitchConnection networkSwitchConnection) 
    { 
     _localControllerInfo = localControllerInfo; 
     _arduinoInjector = arduinoInjector; 
     _inputWriters = inputWriters; 
     _networkSwitchConnection = networkSwitchConnection; 
     // This assumption might not always be true, but there is no way for now to get the input state 
     _inputStates = Enumerable.Repeat(InputState.Normal, _inputWriters.Length).ToArray(); 
     // This assumption might not always be true, but there is no way for now to get the connection state 
     _isUnitConnected = true; 
    } 

    public LocalControllerTypes.LocalController LocalControllerInfo 
    { 
     get 
     { 
      return _localControllerInfo; 
     } 
     set 
     { 
      if (_localControllerInfo != value) 
      { 
       _localControllerInfo = value; 
       RaisePropertyChanged(); 
      } 
     } 
    } 

    public LocalControllerTypes.ArduinoInjector[] ArduinoInjectors 
    { 
     get 
     { 
      return _arduinoInjector; 
     } 
     set 
     { 
      if (_arduinoInjector != value) 
      { 
       _arduinoInjector = value; 
       RaisePropertyChanged(); 
      } 
     } 
    } 

    public WebWriter.WebWriter[] InputWriters 
    { 
     get 
     { 
      return _inputWriters; 
     } 
     set 
     { 
      if (_inputWriters != value) 
      { 
       _inputWriters = value; 
       RaisePropertyChanged(); 
      } 
     } 
    } 

    public SNMPNetworkSwitchConnection.SNMPNetworkSwitchConnection NetworkSwitchConnection 
    { 
     get 
     { 
      return _networkSwitchConnection; 
     } 
     set 
     { 
      if (_networkSwitchConnection != value) 
      { 
       _networkSwitchConnection = value; 
       RaisePropertyChanged(); 
      } 
     } 
    } 

    public InputState[] InputStates 
    { 
     get 
     { 
      return _inputStates; 
     } 
     set 
     { 
      if (_inputStates != value) 
      { 
       _inputStates = value; 
       RaisePropertyChanged(); 
      } 
     } 
    } 

    public bool IsUnitConnected 
    { 
     get 
     { 
      return _isUnitConnected; 
     } 
     set 
     { 
      if (_isUnitConnected != value) 
      { 
       _isUnitConnected = value; 
       RaisePropertyChanged(); 
      } 
     } 
    } 
} 

MainViewModel.cs:

public class MainViewModel : INotifyPropertyChanged 
{ 
    private Unit _selectedUnit; 
    private ObservableCollection<Unit> _units; 
    private string _reader1RawCardData; 
    private string _reader2RawCardData; 
    private int _reader1BitsCount; 
    private int _reader2BitsCount; 

    public event PropertyChangedEventHandler PropertyChanged; 

    public MainViewModel(IUnitStore unitStore) 
    { 
     UnitStore = unitStore; 

     // We could use directly the unitstore instead of creating another container and binding on that, but 
     // not doing so will allow us to add unit filtering further down the road 
     _units = new ObservableCollection<Unit>(unitStore.Units); 
     _selectedUnit = _units.First(); 

     _reader1RawCardData = ""; 
     _reader2RawCardData = ""; 
     _reader1BitsCount = 0; 
     _reader2BitsCount = 0; 
    } 

    protected void RaisePropertyChanged([CallerMemberName]string propertName = "") 
    { 
     var temp = PropertyChanged; 
     if (temp != null) 
     { 
      temp(this, new PropertyChangedEventArgs(propertName)); 
     } 
    } 

    protected void RefreshUnitStore(object obj) 
    { 
     UnitStore.UpdateStore(); 
     Units = new ObservableCollection<Unit>(UnitStore.Units); 
     SelectedUnit = Units.First(); 
    } 

    protected void SendReaderCardSwipe(object obj) 
    { 
     int unitReaderNumber = (int)obj; 
     IPAddress arduinoIp = SelectedUnit.LocalControllerInfo.Readers[unitReaderNumber - 1].InjectorIp; 
     int injectorNumber = SelectedUnit.LocalControllerInfo.Readers[unitReaderNumber - 1].InjectorNumber; 
     string serviceUrl = SelectedUnit.ArduinoInjectors.Where(injector => injector.Ip.Equals(arduinoIp)).First().Url; 

     InjectorInterface.CardSwipe<IPAddress>(serviceUrl, arduinoIp, injectorNumber, Reader1BitsCount, Reader1RawCardData); 
    } 

    protected void UpdateSelectedUnitConnectionState(object obj) 
    { 
     ((INetworkConnection.INetworkConnection)SelectedUnit.NetworkSwitchConnection).SetConnection(SelectedUnit.IsUnitConnected); 
    } 

    public IUnitStore UnitStore 
    { 
     get; 
     private set; 
    } 

    public Unit SelectedUnit 
    { 
     get 
     { 
      return _selectedUnit; 
     } 
     set 
     { 
      if (_selectedUnit != value) 
      { 
       _selectedUnit = value; 
       RaisePropertyChanged(); 
      } 
     } 
    } 

    public ObservableCollection<Unit> Units 
    { 
     get 
     { 
      return _units; 
     } 
     set 
     { 
      if (_units != value) 
      { 
       _units = value; 
       RaisePropertyChanged(); 
      } 
     } 
    } 

    public string Reader1RawCardData 
    { 
     get 
     { 
      return _reader1RawCardData; 
     } 
     set 
     { 
      if (_reader1RawCardData != value) 
      { 
       _reader1RawCardData = value; 
       RaisePropertyChanged(); 
      } 
     } 
    } 

    public string Reader2RawCardData 
    { 
     get 
     { 
      return _reader2RawCardData; 
     } 
     set 
     { 
      if (_reader2RawCardData != value) 
      { 
       _reader2RawCardData = value; 
       RaisePropertyChanged(); 
      } 
     } 
    } 

    public int Reader1BitsCount 
    { 
     get 
     { 
      return _reader1BitsCount; 
     } 
     set 
     { 
      if (_reader1BitsCount != value) 
      { 
       _reader1BitsCount = value; 
       RaisePropertyChanged(); 
      } 
     } 
    } 

    public int Reader2BitsCount 
    { 
     get 
     { 
      return _reader2BitsCount; 
     } 
     set 
     { 
      if (_reader2BitsCount != value) 
      { 
       _reader2BitsCount = value; 
       RaisePropertyChanged(); 
      } 
     } 
    } 

    public ICommand RefreshSourceCommand 
    { 
     get 
     { 
      return new RelayCommand(RefreshUnitStore); 
     } 
    } 

    public ICommand SendReaderCardSwipeCommand 
    { 
     get 
     { 
      return new RelayCommand(SendReaderCardSwipe); 
     } 
    } 

    public ICommand UpdateSelectedUnitConnectionStateCommand 
    { 
     get 
     { 
      return new RelayCommand(UpdateSelectedUnitConnectionState); 
     } 
    } 
} 

回答

0

ItemsControl勢必SelectedUnit.LocalControllerInfo.Inputs。什麼是.Inputs的類型?

正如你寫的你的綁定將無法訪問InputStateInputName。這不是真正的「如何標識陣列項目有什麼枚舉去」

爲了解決原來的問題,一種可能是嵌套一些元組並綁定到的範圍,一拉

List<Tuple<int,State>> States = new List<Tuple<int,State>>(); 

States.Add(new Tuple<int, State>(1,State.Bar)); 
States.Add(new Tuple<int, State>(2, State.Foo)); 
States.Add(new Tuple<int, State>(3, State.Bar));