none
ListView и его возможности RRS feed

  • Вопрос

  • Возможно ли в ListView сделать отображение Tile-в (Для режима отображения Tile) аналогично проводнику windows 7. а именно мне нужна строка состояния памяти. Подскажите и растолкуйте)))) За ранее благодарен!!!!!!
    • Изменено Dobrii 21 января 2013 г. 11:38
    21 января 2013 г. 11:37

Ответы

  • Слепил на коленке:

    var imageList = new ImageList();
    imageList.ImageSize = SystemIcons.Question.Size;
    imageList.Images.Add(SystemIcons.Question);
    imageList.Images.Add(SystemIcons.Information);
    
    int sizeWidth = SystemIcons.Error.Width;
    
    var listView = new ListView
    {
        Parent = this,
        Dock = DockStyle.Fill,
        View = View.Tile,
        LargeImageList = imageList,
        OwnerDraw = true
    };
    var item1 = new ListViewItem("Disk C:", 0);
    var item2 = new ListViewItem("Disk D:", 1);
    listView.Items.Add(item1);
    listView.Items.Add(item2);
    
    listView.DrawItem += (o, e) =>
    {
        int x = e.Bounds.X;
        int y = e.Bounds.Y;
        int h = e.Bounds.Height;
        int w = e.Bounds.Width;
    
        e.Graphics.DrawString(e.Item.Text, listView.Font, Brushes.Black, x + sizeWidth, y);
        e.Graphics.DrawImage(imageList.Images[e.Item.ImageIndex], x, y);
        e.Graphics.DrawRectangle(Pens.LightSeaGreen, x + sizeWidth, y + h / 3, x + w - sizeWidth, 10);
        e.Graphics.FillRectangle(Brushes.LightSeaGreen, x + sizeWidth, y + h / 3, 20, 10);
        e.Graphics.DrawString("Memory info here", listView.Font, Brushes.Gray, x + sizeWidth, y + h - h / 3);
    };

    В качестве картинок дисков взял системные иконки.

    Шрифты и цвета подобрать по вкусу.

    Информация об объёме и заполненности диска, конечно, должна дополнительно получаться.

    Число 20 в методе FillRectangle означает заполненность диска. Тоже должно получаться дополнительно.

    • Предложено в качестве ответа Abolmasov Dmitry 23 января 2013 г. 8:20
    • Помечено в качестве ответа Dobrii 25 января 2013 г. 8:22
    22 января 2013 г. 10:17

Все ответы

  • Я так понимаю речь о WinRT. Настройка Tile-в достаточно ограничена и позволяет использовать ряд шаблонов

    Подробнее читайте тут и по ссылкам внизу статьи.


    Женат на WPF. Тайно встречаюсь с WinRT. Не сложилось с C#!

    21 января 2013 г. 12:53
    Отвечающий
  • Нет, речь не о WinRT. У ListView есть свойство View  принимающее значения: LargeIcon, Details, SmallIcon, List, Tile. Собственно речь идет о последнем режиме, но не под Windows 8, а под Windows 7
    22 января 2013 г. 5:21
  • В WinForms, если честно, как такое сделать не знаю, но могу предложить реализовать именно этот элемент управления на WPF и интегрировать его в приложение через ElementHost.
    22 января 2013 г. 5:53
  • В WinForms, вым придется полностью переопределять отрисовку таких элементов. Для WPF, достаточно задать DataTemplate.

    22 января 2013 г. 6:36
    Отвечающий
  • а можно поподробнее пожалуйста. приведите пример!!!

    22 января 2013 г. 8:12
  • Слепил на коленке:

    var imageList = new ImageList();
    imageList.ImageSize = SystemIcons.Question.Size;
    imageList.Images.Add(SystemIcons.Question);
    imageList.Images.Add(SystemIcons.Information);
    
    int sizeWidth = SystemIcons.Error.Width;
    
    var listView = new ListView
    {
        Parent = this,
        Dock = DockStyle.Fill,
        View = View.Tile,
        LargeImageList = imageList,
        OwnerDraw = true
    };
    var item1 = new ListViewItem("Disk C:", 0);
    var item2 = new ListViewItem("Disk D:", 1);
    listView.Items.Add(item1);
    listView.Items.Add(item2);
    
    listView.DrawItem += (o, e) =>
    {
        int x = e.Bounds.X;
        int y = e.Bounds.Y;
        int h = e.Bounds.Height;
        int w = e.Bounds.Width;
    
        e.Graphics.DrawString(e.Item.Text, listView.Font, Brushes.Black, x + sizeWidth, y);
        e.Graphics.DrawImage(imageList.Images[e.Item.ImageIndex], x, y);
        e.Graphics.DrawRectangle(Pens.LightSeaGreen, x + sizeWidth, y + h / 3, x + w - sizeWidth, 10);
        e.Graphics.FillRectangle(Brushes.LightSeaGreen, x + sizeWidth, y + h / 3, 20, 10);
        e.Graphics.DrawString("Memory info here", listView.Font, Brushes.Gray, x + sizeWidth, y + h - h / 3);
    };

    В качестве картинок дисков взял системные иконки.

    Шрифты и цвета подобрать по вкусу.

    Информация об объёме и заполненности диска, конечно, должна дополнительно получаться.

    Число 20 в методе FillRectangle означает заполненность диска. Тоже должно получаться дополнительно.

    • Предложено в качестве ответа Abolmasov Dmitry 23 января 2013 г. 8:20
    • Помечено в качестве ответа Dobrii 25 января 2013 г. 8:22
    22 января 2013 г. 10:17
  • ну да все просто!!!!!!!! что я не сообразил сразу. Надоело просто постоянно переписывать DrawItem. Везде где не использую ListView, везде переписываю отрисовку элементов)))))))) а как это реализовать с помощью WPF???
    22 января 2013 г. 10:30
  • Ну например, вот так.

    1. Создаем WPF проект и добавляем в него вот такой класс:

    public class Disk
    {
        public string Name { get; set; }
        public double Size { get; set; }
        public double Used { get; set; }
        public string Free { get; set; }
    }

    2. Меняем разметку главного окна:

    <Grid>
        <ListView x:Name="lvDrives">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <StackPanel Width="200">
                        <TextBlock Text="{Binding Name}" />
                        <ProgressBar Maximum="{Binding Size}" Value="{Binding Used}" />
                        <TextBlock Text="{Binding Free}" Foreground="Gray" />
                    </StackPanel>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </Grid>

    3. Код главного окна:

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            Loaded += new RoutedEventHandler(MainWindow_Loaded);
        }
    
        void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            lvDrives.ItemsSource = DriveInfo.GetDrives().Select(
                di => new Disk
                {
                    Name = string.Format("{0} ({1}:)", di.VolumeLabel, di.Name),
                    Size = Math.Truncate(di.TotalSize / (1024d * 1024 * 1024)),
                    Used = Math.Truncate((di.TotalSize - di.AvailableFreeSpace) / (1024d * 1024 * 1024)),
                    Free = string.Format("{0} ГБ свободно из {1} ГБ", Math.Truncate(di.AvailableFreeSpace / (1024d * 1024 * 1024)), Math.Truncate(di.TotalSize / (1024d * 1024 * 1024)))
                }
                );
        }
    }

    4. Запускаем:

    Я делал быстро, поэтому внешний вид не полностью скопирован. Но можно и поиграться. Например так:

    <Grid>
        <ListView x:Name="lvDrives" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
            <ListView.ItemsPanel>
                <ItemsPanelTemplate>
                    <WrapPanel />
                </ItemsPanelTemplate>
            </ListView.ItemsPanel>
            <ListView.ItemTemplate>
                <DataTemplate>
                    <StackPanel Width="200">
                        <TextBlock Text="{Binding Name}" />
                        <ProgressBar Maximum="{Binding Size}" Value="{Binding Used}" Height="20"  />
                        <TextBlock Text="{Binding Free}" Foreground="Gray" />
                    </StackPanel>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </Grid>

    Тогда визуально это будет вот так:

    Как видите, отображение полностью отделено от обработки, что во многих случаях весьма удобно.

    • Предложено в качестве ответа Abolmasov Dmitry 23 января 2013 г. 8:20
    22 января 2013 г. 12:00
    Отвечающий
  • а именно мне нужна строка состояния памяти.

    Я только сейчас обратил внимание на процитированные слова. Если отображать полосу (прогресс-бар) не надо, то в ручной отрисовке DrawItem нет необходимости. Достаточно задать SubItem, и добавить колонки в listView. И вторая строка текста (которая в SubItem) будет отображаться сама.

    • Предложено в качестве ответа Abolmasov Dmitry 23 января 2013 г. 8:20
    22 января 2013 г. 13:11
  • Привет.

    Пожалуйста, не завыбайте отмечать сообщение или сообщения, являющиеся решением вашей проблемы (кнопка "Пометить как ответ").

    Спасибо.


    Для связи [mail]

    23 января 2013 г. 8:20
  • Надоело просто постоянно переписывать DrawItem. Везде где не использую ListView, везде переписываю отрисовку элементов

    Там всего-то пять строк кода отрисовки.

    Могу предложить другой способ. Сымитировать то же, как это делается в WPF: вкладыванием одних контролов в другие.

    var flowLayoutPanel = new FlowLayoutPanel { Parent = this, Dock = DockStyle.Fill };
    
    foreach (var drive in DriveInfo.GetDrives())
    {
        var panel = new FlowLayoutPanel { Parent = flowLayoutPanel };
    
        var driveImage = SystemIcons.Question.ToBitmap();
    
        var pictureBoxDrive = new PictureBox { Parent = panel, Size = driveImage.Size, Image = driveImage };
        var labelName = new Label { Parent = panel, Text = drive.Name };
        var progressBar = new ProgressBar { Parent = panel, Style = ProgressBarStyle.Continuous };
        var labelMemory = new Label { Parent = panel, AutoSize = true };
    
        if (drive.IsReady)
        {
            int freeSpace = (int)(drive.AvailableFreeSpace / 1024 / 1024 / 1024);
            int totalSize = (int)(drive.TotalSize / 1024 / 1024 / 1024);
            labelMemory.Text = freeSpace + " свободно из " + totalSize;
            progressBar.Maximum = totalSize;
            progressBar.Value = totalSize - freeSpace;
        }
        else
        {
            labelMemory.Text = "Drive is removable";
        }
    }

    Вот только в коде не видна иерархия вложенности. Не позволяет C# отобразить наглядно, как в xaml.

    23 января 2013 г. 10:47
  • Всем спасибо. использовал DrawItem.Все красиво!!!!!!!!!!!!!!!!!!!!!!!
    25 января 2013 г. 8:22