Как правильно представить список UserControls с использованием WPF MVVM без использования кода позади? - PullRequest
0 голосов
/ 25 января 2019

Я пытаюсь создать программу WPF MVVM, в которой клиент загружает список файлов с сервера, показывает их пользователю и разрешает им загружать эти файлы.

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

У меня уже есть: Создан BaseViewModel, Создан RelayCommand, Создан MainViewModel, Создан DownloadViewModel, который содержит ObservableCollection RemoteDiscElementViewModels, который является ViewModel одного файла с сервера, Создан RemoteDiscElementView, Создан DownloadView

ObservableCollection загружается правильно, но, поскольку я связываю коллекцию с ItemsControl, необходимое количество визуализаций RemoteDiscElementViews, но все они пусты.

DownloadViewModel:

public class DownloadViewModel : BaseViewModel
{
    public Client Client { get; set; }
    public ObservableCollection<RemoteDiscElementViewModel> RemoteDiscElementViewModels { get; set; }
    public static DownloadViewModel Download1;
    void Awake()
    {
        Download1 = this;
    }
    public DownloadViewModel()
    {
        Client = new Client();
        RemoteDiscElementViewModels = new ObservableCollection<RemoteDiscElementViewModel>();
    }
    public DownloadViewModel(string address, int port)
    {
        Client = new Client(address, port);
        RemoteDiscElementViewModels = new ObservableCollection<RemoteDiscElementViewModel>();
        Client.Connect();
        GetFiles();
    }

    public void GetFiles()
    {
        RemoteDiscElementViewModels.Clear();
        var content = Client.ListFiles();
        foreach(var file in content)
        {
            RemoteDiscElementViewModel newFile = new RemoteDiscElementViewModel(file.Type, file.Filename, file.Filepath, file.Fileext, file.Filesize);
            RemoteDiscElementViewModels.Add(newFile);
        }
    }



}

RemoteDiscElementViewModel:

public class RemoteDiscElementViewModel : BaseViewModel
{
    private string type;
    private string filename;
    private string filepath;
    private int filesize;
    private string fileext;
    private bool isDownloaded;

    public RemoteDiscElementViewModel()
    {

    }
    public RemoteDiscElementViewModel(string type, string filename, string filepath, string fileext, int filesize)
    {
        Type = type;
        Filename = filename;
        Filepath = filepath;
        Fileext = fileext;
        Filesize = filesize;
        IsDownloaded = false;

    }

    public void Download()
    {
        DownloadViewModel.Download1.Client.SendFile(Filename);
    }
}

RemoteDiscElementView:

 <UserControl x:Class="sikFtpClient.View.RemoteDiscElementView"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:local="clr-namespace:sikFtpClient.View"
         xmlns:vm="clr-namespace:sikFtpClient.ViewModel"
         mc:Ignorable="d" 
         d:DesignHeight="450" d:DesignWidth="800">
<UserControl.DataContext>
    <vm:RemoteDiscElementViewModel/>
</UserControl.DataContext>
<Grid>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="5*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Label Content="{Binding Filename}" Grid.Column="0"/>
        <Button Command="{Binding DownloadCommand}" Grid.Column="1"/>
    </Grid>
</Grid>

Как правильно отобразить ObservableCollection UserControls без использования кода позади?

1 Ответ

0 голосов
/ 25 января 2019

DownloadView можно записать так, например:

<UserControl...>
    <ListBox ItemsSource="{Binding Path=(local:DownloadViewModel.RemoteDiscElementViewModels), Mode=OneWay}">
        <ListBox.ItemTemplate>
            <DataTemplate DataType="{x:Type local:RemoteDiscElementViewModel}">
                <local:RemoteDiscElementView/>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</UserControl>

В «RemoteDiscElementView» вам также не нужен следующий код:

<UserControl.DataContext>
    <vm:RemoteDiscElementViewModel/>
</UserControl.DataContext>

Поскольку DataContext неявно устанавливается ListBox для его дочерних элементов.

Наконец, убедитесь, что «DownloadView» имеет свой DataContext, установленный в объект DownloadViewModel.

Edit:

Добавлены следующие свойства в «RemoteDiscElementViewModel»:

public String Type => _type;
public String Filename => _filename;
public String Filepath => _filepath;
public Int32 Filesize => _filesize;
public String Fileext => _fileext;
public Boolean IsDownloaded => _isDownloaded;

Использованы фиктивные данные для функции Client.ListFiles ():

public List<RemoteDiscElementViewModel> ListFiles() {
    return Enumerable.Range(0, 20).Select(i => new RemoteDiscElementViewModel("type", "file", "filepath", "fileext", 5)).ToList();
}

И использовал конструктор «DownloadViewModel», используя адрес и порт, и он что-то отображал:

Test

...