2016-02-09 83 views
1

我正在嘗試做一個最近的上傳系統,所以我在contextMenu中列出了最後5個(或更少)的上傳。ItemsControl裏面的WPF Menuitem

問題是當我在做靜態測試版本(不是動態的)時,一切都很好。像可以顯示這個截圖:

Everything was fine

現在我的動態版本:

<ItemsControl ItemsSource="{Binding Uploads}"> 
     <ItemsControl.ItemsPanel> 
      <ItemsPanelTemplate> 
       <StackPanel></StackPanel> 
      </ItemsPanelTemplate> 
     </ItemsControl.ItemsPanel> 
     <ItemsControl.ItemTemplate> 
      <DataTemplate> 
       <MenuItem IsCheckable="False" ItemsSource="{Binding}"> 
        <MenuItem.Icon> 
         <Image Source="Resources/upload.ico"></Image> 
        </MenuItem.Icon> 
        <MenuItem.Header> 
         <TextBlock Text="{Binding name}"></TextBlock> 
        </MenuItem.Header> 
        <DataTemplate> 
         <StackPanel> 
          <MenuItem Command="{Binding GoToUrl}" CommandParameter="{Binding url}"> 
           <MenuItem.Header> 
            <Image IsEnabled="False" HorizontalAlignment="Center" Source="{Binding miniature}"></Image> 
           </MenuItem.Header> 
          </MenuItem> 
          <Separator/> 
          <MenuItem IsEnabled="False" IsCheckable="False"> 
           <MenuItem.Header> 
            <StackPanel IsEnabled="False"> 
             <TextBlock IsEnabled="False" Text="{Binding uploadDateText}"></TextBlock> 
             <TextBlock IsEnabled="False" Text="{Binding viewNumberText}"></TextBlock> 
            </StackPanel> 
           </MenuItem.Header> 
          </MenuItem> 
          <Separator/> 
          <MenuItem Header="Copy To Clipboard" Command="{Binding CopyToClip}" CommandParameter="{Binding url}" /> 
          <MenuItem Header="Open in browser" Command="{Binding GoToUrl}" CommandParameter="{Binding url}" /> 
          <MenuItem Header="Delete" Command="{Binding Delete}" CommandParameter="{Binding}" /> 
         </StackPanel> 
        </DataTemplate> 
       </MenuItem> 
      </DataTemplate> 
     </ItemsControl.ItemTemplate> 
    </ItemsControl> 

I got this

問題是,當你有另一個菜單項內的菜單項,有小箭頭,但因爲我用ItemsControl包裝所有,我無法訪問submenuItem,我有一個奇怪的選擇錯誤。

我在this question中看到了有關爲什麼它不能按預期工作的信息。由於itemsControl就像一個menuItem。但我沒有找到辦法以另一種方式去做。

我的目標是MenuItem的「foreach循環」與其中的menuItem。也許我沒有一個好方法。

對不起,我的英語不好,我是法語。

編輯1:

看來我還不夠清楚,所以我添加一些更多的信息。

目標:有多達5個菜單foreach客戶端做了上傳。如果他只做了3,那麼3菜單將在上下文菜單中。 Foreach菜單標題將是他上傳文件的名稱。 如果用戶想要獲得關於上傳的更多信息,他將鼠標懸停在上傳名稱上,然後子菜單將被繪製。 該子菜單會顯示所有關於上載的信息:圖像,大小,上傳時的日期,等...

我怎麼做的:我創建了一個將接收來自Web API所需的所有信息類:上傳

public class Upload 
{ 
    public string uniqueId { get; set; } 
    public DateTime uploadedDateTime { get; set; } 
    public int _viewNumber { get; set; } 
    public string url { get; set; } 
    public string minUrl { get; set; } 
    public string type { get; set; } 
    public int size { get; set; } 
    public string name { get; set; } 

    public BitmapImage miniature 
    { 
     get 
     { 
      BitmapImage bitmap = new BitmapImage(); 
      bitmap.BeginInit(); 
      bitmap.UriSource = new Uri(this.minUrl, UriKind.Absolute); 
      bitmap.EndInit(); 

      return bitmap; 
     } 
    } 

    public string uploadDateText 
    { 
     get 
     { 
      return "Uploaded : " + this.uploadedDateTime.Date.ToString() + " at " + this.uploadedDateTime.TimeOfDay.ToString(); 
     } 
    } 

    public string viewNumberText 
    { 
     get 
     { 
      return "Number of views : " + this._viewNumber; 
     } 
    } 

    public Upload(string p_uniqueId, DateTime p_uploadedDateTime, int p_viewNumber, string p_url, string p_minUrl, string p_type, int p_size, string p_name) 
    { 
     uniqueId = p_uniqueId; 
     uploadedDateTime = p_uploadedDateTime; 
     _viewNumber = p_viewNumber; 
     url = p_url; 
     minUrl = p_minUrl; 
     type = p_type; 
     size = p_size; 
     name = p_name; 
    } 

    public void delete() 
    { 
     MessageBox.Show("Deleting item with id : " + this.uniqueId); 
    } 

    public void refresh() 
    { 

    } 
} 

因此,當我問我的WebApp最近5次上傳我的用戶,我將有一個列表。

含有多達5項

若要使我的ContextMenu這個名單我使用此代碼轉換它在一個ObservableCollection:

public ObservableCollection<Upload> Uploads 
    { 
     get 
     { 
      App.GetAppRef().initUploads(); 
      return App.GetAppRef().Uploads; 
     } 

    } 

我花了很多時間來找到一種方法在我的上下文菜單中有一個可變數量的menuItem。如果用戶只上傳2個文件,確實可以有2個menuItem。這是一種FIFO隊列風格(先進先出),最多5個元素。

所以我看看xaml中的「foreach」等價物。但我只找到一種方法來做一個「xaml foreach」,其ItemsSource綁定到我的ObservableCollection的Upload。

如果有人有更好的想法做到這一點,請告訴我,因爲我知道這可能不是最好的解決方案。

無論如何,我有我的上下文菜單中的這個「最後5上傳」部分之前和之後的其他menuItem,所以我必須做我的foreach在上下文菜單的特定區域內。

什麼問題:現在,我不能去我的subitemMenu,我有我的itemControls啓用的選擇,所以我需要找到一個更好的方式來實現這一點。

我希望我已經澄清了一點我的問題。

+0

不知道我理解你想要達到的目的。通過動態,你的意思是你想要定義一個特定的菜單模板,可以作爲子菜單添加到其他菜單項目中? –

+0

那麼我的webApi會給我用戶上傳的最後一張圖片,我希望我的用戶能夠獲取他們上傳的桌面客戶端上的最後5張圖片。所以我有一個5個對象的數組,我需要用他的名字foreach一個menuitem,如果你讓它在你的光標上,它會顯示更多細節,比如我張貼的截圖。 –

+0

我想我明白你的意思了。這個問題似乎涉及您需要的菜單中的動態/靜態組合:http://stackoverflow.com/questions/14489112/how-do-i-dynamically-bind-and-statically-add-menuitems。至於爲每個動態菜單項添加子菜單,請嘗試將其添加到該問題中給出的答案的部分。 –

回答

0

好吧,我花了一些時間去它,但這裏是一個有效的答案(我從幾個在stackoverflow上找到答案)。
XAML中:

<local:MyStyleSelector x:Key="MyStyleSelector" /> 

<Style x:Key="DynamicItemStyle" TargetType="MenuItem"> 
    <Setter Property="Header" Value="{Binding Path=Title}"/> 
    <Setter Property="ItemsSource"> 
     <Setter.Value> 
      <x:Array Type="FrameworkElement"> 
       <MenuItem Header="Active" IsCheckable="True" IsChecked="{Binding Path=Active}"></MenuItem> 
       <Separator></Separator> 
       <MenuItem Header="Edit" Name="EditCustomMessageButton" Style="{x:Null}"></MenuItem> 
       <MenuItem Header="Delete" Name="DeleteCustomMessageButton" Style="{x:Null}"></MenuItem> 
      </x:Array> 
     </Setter.Value> 
    </Setter> 
</Style> 
<Style x:Key="StaticItemStyle" TargetType="MenuItem"> 
</Style> 

並在代碼:

public class MyStyleSelector : StyleSelector 
    { 
     public override Style SelectStyle(object item, DependencyObject container) 
     { 
      var itemsControl = ItemsControl.ItemsControlFromItemContainer(container); 
      if (item is MyObject) 
       return (Style)itemsControl.FindResource("DynamicItemStyle"); 
      else 
       return (Style)itemsControl.FindResource("StaticItemStyle"); 
     } 
    } 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 
      MyObject dynamicObject = new MyObject(); 
      dynamicObject.Title = "dynamic1"; 
      Windows.Add(dynamicObject); 
      Windows.Add(new MyObject() { Title = "dynamic2" }); 
     } 

     private ObservableCollection<MyObject> _windows = new ObservableCollection<MyObject>(); 


     public ObservableCollection<MyObject> Windows 
     { 
      get { return _windows; } 
      set { _windows = value; } 
     } 
    } 

    public class MyObject 
    { 
     public string Title { get; set; } 
    } 

`

+0

我一直在用另一種方式來實現我的目標,但無論如何,你的代碼完成這項工作與一些ajustements很好的工作。我希望它也能幫助其他人。 –