0

我试图通过实现我自己版本的众所周知的计算器示例来掌握使用 MEF 框架。用户界面在 WPF 中。

合成后,Viewmodel 拥有一个ObservableCollection(Of IOperation)由 View 中的“ListBox”表示的Buttons。每个上的文本都ButtonChar定义IOperation为一个名为 的属性Symbol。通过将 ListBox 的 SelectedItem 绑定到 ViewModel 中的属性,我可以触发 Calculate当前选择的方法,IOperation而无需知道Button按下了哪个方法。(下面的代码说明了这一点。)

但是,现在我需要添加InputBindings到 View ,其中每个KeyBinding都将与SymbolIOperation. 看起来我无法避免实现一个Select Case( switch) 语句来遍历 Viewmodel 的IOperations 集合,以选择应该调用 'Calculate' 方法的那个。

有任何想法吗?

XAML:

<ListBox Grid.Column="1" Grid.Row="3" Name="OperationsList" 
         SelectedItem="{Binding ActiveOperation,Mode=TwoWay}"
         ItemsSource="{Binding Operations}">
         <ListBox.ItemsPanel>
             <ItemsPanelTemplate>
                 <UniformGrid IsItemsHost="True"/>
             </ItemsPanelTemplate>
         </ListBox.ItemsPanel>
         <ListBox.ItemTemplate>
             <DataTemplate>
                 <Button Content="{Binding Symbol}"
                         ToolTip="{Binding Description}"
                         Command="{Binding ElementName=OperationsList, Path=DataContext.ActivateOperation}"
                            Click="Button_Click_1"/>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

操作:

Public Interface IOperation
    Function Calculate() As Double
    Property Left As Double
    Property Right As Double
    Property Symbol As String
    Property Description As String
End Interface

视图模型:

Private _activateOperation As Command
    Public Property ActivateOperation As Command
        Get
            Return _activateOperation
        End Get
        Set(value As Command)
            _activateOperation = value
            OnPropertyChanged()
        End Set
    End Property

Public Property ActiveOperation As IOperation
    Get
        Return _compositor.ActiveOperation
    End Get
    Set(value As ICalculator)
        _compositor.ActiveOperation = value
        OnPropertyChanged()
    End Set
End Property

   Public ReadOnly Property Operations As ObservableCollection(Of IOperation)
        Get
            Return New ObservableCollection(Of ICalculator)(_compositor.Operations)
        End Get
    End Property

   Private Sub DoActivateOperation(Optional parameter As Object = Nothing)
        If Left.HasValue Then
            MakeCalculation()
        Else
            Left = CDbl(Display)
            ClearDisplay()
        End If
    End Sub
4

1 回答 1

1

代码的边缘有点粗糙,因此请进行相应调整...

// in ViewModel, after composition

// map string symbols to input Keys (for brevity, using a Dictionary)
Dictionary<string, System.Windows.Input.Key> SymbolsToKeys = new Dictionary<string, Key>
{
  { "+", Key.Add },
  // etc.
}

// compose the list (expose it via a public property)
// (ensure not to get confused: the KeyValuePair.Key is for the string symbol
// ... and the KeyValuePair.Value is for the Sys.Win.Input.Key value)
KeyBindings = (from symbolAndKey in SymbolsToKeys
               join op in Operations on Equals(symbolAndKey.Key, op.Symbol)
               select new KeyBinding(
                 new Command(op.Calculate)),
                 new KeyGesture(symbolAndKey.Value)
              ).ToList();

// in View, after Binding to ViewModel
var vm = DataContext as YourViewModel;
if(vm != null)
{
   foreach(var keybinding in vm.KeyBindings){
       this.InputBindings.Add(keybinding);
   }
}
于 2013-01-03T20:10:29.987 回答