ItemsControl

时间:2016-02-09 07:31:42

标签: c# wpf

我正在尝试使用最近的上传系统,因此我在contextMenu中列出了最近5次(或更少)上传。

问题是我在做静态测试版本(不是动态的)时一切都很好。就像可以显示这个截图:

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

问题是当你在另一个menuItem中有一个menuItem时,有一个小箭头,但由于我已经用ItemsControl包装了所有,我无法访问submenuItem,我有一个奇怪的选择错误。

我在this question中看到了有关它为什么没有按预期工作的信息。由于itemsControl就像一个menuItem。但我没有办法以另一种方式做到这一点。

我的目标是MenuItem的“foreach循环”,其中包含其他menuItem。也许我没有一个好的方法。

P.S:对不起我的英语不好,我是法国人。

编辑1:

看来我不够清楚,所以我添加了更多信息。

目标:最多有5个菜单foreach上传客户端已完成。如果他只做了3,那么3 Menu将出现在上下文菜单中。 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”等价物。但是我只找到了一种方法来使用ItemsControl进行“xaml foreach”,并将itemSource绑定到我的ObservableCollection上传。

如果有人有更好的想法,请告诉我,因为我知道这可能不是最好的解决方案。

无论如何,我在上下文菜单中的“last 5 upload”部分之前和之后都有其他menuItem,所以我必须在上下文菜单的特定区域内执行foreach。

问题是什么:现在,我无法继续使用我的subitemMenu,并且我已经为我的itemControls启用了选项,所以我需要找到一种更好的方法来实现这一点。

我希望我已经澄清了我的问题。

1 个答案:

答案 0 :(得分: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; }
    }

`