2013-02-25 30 views
0

在我的视图模型中,我有一些数学函数,如加,减。在我的用户界面中,我有两个文本框将包含一个输入,然后有一个组合框。这个组合框将包含所有数学函数的名称(加,减)。然后在确定按钮上,我想要选择的功能被执行。我如何做到这一点。我的意思是如何在组合框中显示函数名称列表?我可以在那里显示字符串,但函数名称如何。并选择功能。制作函数列表

<ComboBox ItemsSource="{Binding Actions}" SelectedItem="{Binding SelectedAction}" /> 

视图模型

public IEnumerable<string> Actions 
{ 
    get 
    { 
     var list = new List<string>(); 
     list.Add("Add");  // Instead of adding strings, I want to add functions. 
     list.Add("Subtract"); 
     return list; 
    } 
} 

public int AddFunction() 
{ 
    return numberA + numberB; 
} 

public int SubtractFunction() 
{ 
    return numberA - numberB; 
} 
+0

你要在增加功能的'ComboBox'或函数的名称?即。 'string's。 – Guillaume 2013-02-25 07:08:25

+0

函数名称实际上。在这种情况下,组合框将包含AddFunction,SubtractFunction。 – 2013-02-25 07:25:54

+0

简而言之,它应该像我从组合框中选择功能,然后单击确定。点击确定,我不检查什么是combox框的值。我只是做了selectedAction.Exceute(或类似的东西)。我不想如果其他检查,如果combox框字符串是添加然后执行这个否则做到这一点。 – 2013-02-25 07:27:46

回答

1

下面一个例子,可以帮助:

TODO: 1的结果应该以绑定在UI 2. ComboBox_SelectionChanged另一个文本块应通过做ICommand的。参考文献:mvvm-binding-treeview-item-changed-to-icommand

public IList<MyComboboxItem> Actions 
    { 
     get 
     { 
      var list = new List<MyComboboxItem> { new MyComboboxItem(AddFunction), new MyComboboxItem(SubtractFunction) }; 
      return list; 
     } 
    } 

    public int numberA { get; set; } 
    public int numberB { get; set; } 

    public int Result { get; private set; } 

    public void AddFunction() 
    { 
     Result = numberA + numberB; 
    } 

    public void SubtractFunction() 
    { 
     Result = numberA - numberB; 
    } 

    private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) 
    { 
     var comboboxItem = e.AddedItems[0] as MyComboboxItem; 
     if (comboboxItem != null) 
      comboboxItem.Action.Invoke(); 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 




    public class MyComboboxItem 
    { 
    public Action Action { get; private set; } 

    public MyComboboxItem(Action action) 
    { 
     this.Action = action; 
    } 

    public override string ToString() 
    { 
     return Action.Method.Name; 
    } 
} 
1

所以,你想要的是有代表的名单,然后一个转换器,将委托转换为方法名。

在你的ViewModel中,让Actions属性返回一个代表列表。使用预定义的Func,这是一种不带参数并返回int的方法:

public IEnumerable<Func<int>> Actions 
{ 
    get 
    { 
     List<Func<int>> list = new List<Func<int>>(); 
     list.Add(AddFunction); 
     list.Add(SubstractFunction); 
     return list; 
    } 
} 

接下来,实现一个转换器。通常情况下,转换器是“视图”的一部分,所以把它放在cs文件后面的代码中。这种转换转换Func<int>为字符串,它使用反射来做到这一点:

[ValueConversion(typeof(Func<int>), typeof(string))] 
public class FnConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     Func<int> fn = value as Func<int>; 
     return fn.Method.Name; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     return null; 
    } 
} 

最后,你需要使用转换器在XAML。但为此,您需要指定应用转换器的组合框的项目模板。

<!-- earlier in code define the converter as a resource --> 
<Window.Resources> 
    <src:FnConverter x:Key="conv" /> 
</Window.Resources> 

... 

<!-- now the combo box --> 
<ComboBox Margin="4" ItemsSource="{Binding Path=Actions}"> 
    <ComboBox.ItemTemplate> 
     <DataTemplate> 
      <TextBlock Text="{Binding Path=., Converter={StaticResource conv}}" /> 
     </DataTemplate> 
    </ComboBox.ItemTemplate> 
</ComboBox> 

说了这样的话,我认为更优雅的解决方案是在视图模型中保留一个MethodInfo列表。使用自定义属性生成此列表。在一些代码下面。请注意以下几点:

  1. PresentingAttribute是一个自定义属性。它来自System.Reflection.Attribute。它什么都没有。您可以添加参数,如“标签”,“描述”等。
  2. 装饰你想在组合框中使用`[Presenting]'的方法
  3. 现在,动作使用反射。请注意筛选谓词的“Where”和lambda,它只返回具有我们自定义属性的方法。
  4. 您必须修改转换器才能使用MethodInfo。
namespace SO 
{ 
    class PresentingAttribute : Attribute 
    { 
    } 

    class FnVM 
    { 
     public int numA { get; set; } 
     public int numB { get; set; } 

     public IEnumerable<MethodInfo> Actions 
     { 
      get 
      { 
       return typeof(FnVM).GetMethods().Where(minfo => 
        minfo.GetCustomAttribute(typeof(PresentingAttribute)) != null 
       ); 
      } 
     } 


     [Presenting] 
     public int AddFunction() 
     { 
      return numA + numB; 
     } 

     [Presenting] 
     public int MulFunction() 
     { 
      return numA * numB; 
     } 

    } 
}