2013-04-09 28 views
2

我加載編程一個radMenu使用Caliburn.Micro沒有問題,XAML中看起來是這樣的:RadMenu和RadMenuItem Caliburn.Micro

<telerik:RadMenu ItemsSource="{Binding .MenuItems}" 
       VerticalAlignment="Top" 
       cal:Action.TargetWithoutContext="{Binding RelativeSource={RelativeSource Self}}" 
       cal:Message.Attach="[Event ItemClick] = [Action MenuItemClick($this)]"> 
    <telerik:RadMenu.ItemContainerStyle> 
    <Style TargetType="telerik:RadMenuItem"> 
     <Setter Property="Tag" 
       Value="{Binding .Tag}" /> 
     <Setter Property="Header" 
       Value="{Binding .Text}" /> 
     <Setter Property="Icon" 
       Value="{Binding .Image}" /> 
     <Setter Property="ItemsSource" 
       Value="{Binding .SubItems}" /> 
     <Setter Property="Command" 
       Value="{Binding .SubItems}" /> 
    </Style> 
    </telerik:RadMenu.ItemContainerStyle> 
</telerik:RadMenu> 

在我的ViewModel我有我從數據庫中填寫相應的MenuItems屬性。代碼如下所示:

Property MenuItems As New ObservableCollection(Of MenuItem) 

Public Sub MenuItemClick(item As MenuItem) 
    MessageBox.Show(item.Tag) 
End Sub 

的問題是itemClick事件的線路,我需要接受radMenuItem對象,我的意思是,我需要知道哪個菜單項被點擊了。

I'v在Action.TargetWithoutContext屬性上嘗試過各種組合,到目前爲止,我只獲得MenuItems集合。

在此先感謝

回答

1

的點擊項目將在RadRoutedEventArgs的事件回調在屬性OriginalSource。 例如

void RadMenu_ItemClick(object sender, Telerik.Windows.RadRoutedEventArgs e) 
{ 
    var menuItem = e.OriginalSource as RadMenuItem; 
} 

由於RadRoutedEventArgs子類System.Windows.EventArgs你應該能夠提取任意OriginalSource

有一對夫婦的方法(其中一個我覺得是這樣做的更好方式)

方法1(的作品,但太多的工作在VM我喜歡):

只是通過你的虛擬機事件參數的處理方法,那麼你就可以在VM代碼

cal:Message.Attach="[Event ItemClick] = [Action MenuItemClick($eventargs)]" 

public class ViewModel 
{ 
    public void MenuItemClick(System.Windows.EventArgs e) 
    { 
     var menuItem = e.OriginalSource; 
     // menuItem should be RadMenuItem, you can use FrameworkElement base type to get DataContext 
     var fe = menuItem as FrameworkElement; 
     var data = fe.DataContext; // (obviously do your null checks etc!) 
    } 
} 

但是提取所選擇的項目,這有它離開VM問題了解如何從事件中獲取所選項目。

我假設你MenuItem類是一個自定義類:如果你改變你使用等

方法2的控制,我不喜歡這種方法,它更是不易斷裂?你並不是真的想在你的虛擬機代碼中依賴第三方類型(如果你改變爲另一個控制提供者,比如Infragistics或者你有什麼),所以你應該在實際點擊時將實際的綁定對象傳回給你的viewmodel 。如果不是這種方法仍然有效(但你會在你的虛擬機一個RadMenuItem參考結束)

您可以提取通過自定義Caliburn.Micro的MessageBinder.SpecialValues收集originalsource或實際綁定項,然後直接傳遞所選項目到VM。(你可以把這個代碼放到你的Bootstrapper某處)

這裏獲得綁定到所選的菜單項中的數據項的方法:

MessageBinder.SpecialValues.Add("$selecteditem", (context) => 
{ 
    if (context.EventArgs is EventArgs) 
    {   
     var e = context.EventArgs as EventArgs; 

     // If the control is a FrameworkElement it will have a DataContext which contains the bound item 
     var fe = e.OriginalSource as FrameworkElement; 

     if (fe != null) 
      return fe.DataContext; 
    } 

    return null; 
}); 

如果你想實際RadMenuItem本身你可以改變的上述實施:

MessageBinder.SpecialValues.Add("$selecteditem", (context) => 
{ 
    if (context.EventArgs is EventArgs) 
    {   
     var e = context.EventArgs as EventArgs; 
     return e.OriginalSource; 
    } 

    return null; 
}); 

而在XAML使用方法:

cal:Message.Attach="[Event ItemClick] = [Action MenuItemClick($selecteditem)]" 

這種方法的好處是,視圖模型簡單地接收綁定項,它並不需要知道如何提取值:

public class ViewModel 
{ 
    public void MenuItemClick(TheActualTypeThatWasBound item) 
    { 
     // Do stuff with item 
    } 
} 

當然,除非你傳回的實際菜單項:

public class ViewModel 
{ 
    public void MenuItemClick(RadMenuItem item) 
    { 
     // Do stuff with item 
     var boundData = item.DataContext; 
    } 
} 

但我強烈建議不要這樣做(我有使用Rad公司控制相當不錯的規模的項目,我從來沒有需要從虛擬機中的任何拉德控制參考)

對不起,我不能回覆ŸVB它,因爲我不使用VB,但你可以在這個網站上進行轉換:

http://www.developerfusion.com/tools/convert/vb-to-csharp/

免責聲明:

$selecteditem可能是因爲它的名聲 - 也許$originalsourcedatacontext但是這是一個有點滿口:)

+0

我最終使用了你提到的第一種方法工作,但現在我正在閱讀你的答案我現在正在改變它。感謝您花時間回答我已經學到了很多答案。 – Okura 2013-04-17 02:31:08