绑定列表视图项模板图像到ObservableCollection不起作用

时间:2017-09-19 19:09:50

标签: image listview binding uwp

我知道有很多关于此的问题,我搜索了很多并尝试了我发现的所有内容,但我无法使其正常工作。 简单地说,由于某种原因,我无法在ListView项目模板中显示图像。

所以我有这个ItemViewModel类:

public class ItemViewModel : BaseViewModel, IItemViewModel
{
    public ItemViewModel()
    {
        if (dalInterface == null)
        {
            dalInterface = ApplicationContext.Container.Resolve<IDalInterface>();
        }
        if (eventCenter == null)
        {
            eventCenter = ApplicationContext.Container.Resolve<IEventCenter>();
        }

        SaveCommand = new Command(SaveChanges, true);
        DeleteCommand = new Command(RemoveItem, true);
        AddNewItemCommand = new Command(AddNewItem, true);
    }

    public ICommand SaveCommand { get; set; }

    public ICommand DeleteCommand { get; set; }

    public ICommand AddNewItemCommand { get; set; }

    private Item data;

    public int ID { get; private set; }

    private string title;
    public string Title
    {
        get { return title; }
        set
        {
            title = value;
            NotifyPropertyChanged("Title");
        }
    }

    private string author;
    public string Author
    {
        get { return author; }
        set
        {
            author = value;
            NotifyPropertyChanged("Author");
        }
    }

    private string shortDescription;
    public string ShortDescription
    {
        get { return shortDescription; }
        set
        {
            shortDescription = value;
            NotifyPropertyChanged("ShortDescription");
        }
    }

    private string buyPrice;
    public string BuyPrice
    {
        get { return buyPrice; }
        set
        {
            buyPrice = value;
            NotifyPropertyChanged("BuyPrice");
        }
    }

    private string borrowPrice;
    public string BorrowPrice
    {
        get { return borrowPrice; }
        set
        {
            borrowPrice = value;
            NotifyPropertyChanged("BorrowPrice");
        }
    }

    private int quantity;
    public int Quantity
    {
        get { return quantity; }
        set
        {
            quantity = value;
            NotifyPropertyChanged("Quantity");
        }
    }


    private string detailedDescription;
    public string DetailedDescription
    {
        get { return detailedDescription; }
        set
        {
            detailedDescription = value;
            NotifyPropertyChanged("DetailedDescription");
        }
    }

    private string imagePath;
    public string ImagePath
    {
        get { return imagePath; }
        set
        {
            imagePath = value;
            NotifyPropertyChanged("ImagePath");
        }
    }
    private Image image;
    public Image Image
    {
        get { return image; }
        set
        {
            image = value;
            NotifyPropertyChanged("Image");
        }
    }

    public void SetData(Item item)
    {
        data = item;
        ID = data.ID;
        Author = data.Author;
        Title = data.Title;
        Quantity = data.Quantity;
        ShortDescription = data.ShortDescription;
        DetailedDescription = data.DetailedDescription;
        BuyPrice = data.BuyPrice;
        BorrowPrice = data.BorrowPrice;
        Image = GetImage(data.ImagePath);
    }

    private Image GetImage(string imagePath)
    {
        var imageUri = new Uri(imagePath, UriKind.RelativeOrAbsolute);
        var bitmapImage = new BitmapImage(imageUri);
        var image = new Image
        {
            Source = bitmapImage
        };

        return Image;
    }
    private void SaveChanges()
    {
        UpdateChanges(data);
        dalInterface.UpdateItem(data);
    }

    private void RemoveItem()
    {
        dalInterface.RemoveItem(data);
    }

    private void AddNewItem()
    {
        var newItem = new Item();
        if (AllDataCorrect())
        {
            UpdateChanges(newItem);
            dalInterface.AddNewItem(newItem);
            eventCenter.Publish(new AddItemEventArgs { OperationSuccess = true });
        }
        else
        {
            eventCenter.Publish(new AddItemEventArgs { OperationSuccess = false });
        }
    }

    private void UpdateChanges(Item itemToUpdate)
    {
        itemToUpdate.Author = Author;
        itemToUpdate.Title = Title;
        itemToUpdate.BorrowPrice = BorrowPrice;
        itemToUpdate.BuyPrice = BuyPrice;
        itemToUpdate.DetailedDescription = DetailedDescription;
        itemToUpdate.ShortDescription = ShortDescription;
        itemToUpdate.Quantity = Quantity;
        itemToUpdate.ImagePath = ImagePath;
    }

    private bool AllDataCorrect()
    {
        float val = -1.0F;

        float.TryParse(BuyPrice, out val);
        if (val <= 0.0F)
        {
            return false;
        }

        float.TryParse(BorrowPrice, out val);
        if (val <= 0.0F)
        {
            return false;
        }

        if ((ShortDescription == string.Empty) ||
            (DetailedDescription == string.Empty) ||
            (Author == string.Empty) ||
            (Title == string.Empty)
          )
        {
            return false;
        }

        if (Quantity <= 0)
        {
            return false;
        }

        return true;
    }

    public void Clear()
    {
        Author = string.Empty;
        Title = string.Empty;
        ImagePath = string.Empty;
        ShortDescription = string.Empty;
        DetailedDescription = string.Empty;
        BuyPrice = string.Empty;
        BorrowPrice = string.Empty;
        Quantity = 0;
    }
}

对于本课程,我有以下用户控件:

    <Grid>

    <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition/>
    </Grid.ColumnDefinitions>

    <Grid Grid.Column="0">
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>

        <Grid Grid.Row="0">
            <Grid.ColumnDefinitions>
                <ColumnDefinition/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>

            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>

            <Border Grid.Row="0"
                    Grid.Column="0"
                    Grid.RowSpan="4"
                    Style="{StaticResource ImageBorderStyle}">
                <Image Source="{Binding Image, Mode=TwoWay}"
                       MinWidth="80"
                       MinHeight="80"
                       Stretch="UniformToFill"/>
            </Border>

            <Border Grid.Row="0"
                    Grid.Column="1"
                    Style="{StaticResource BaseBorderStyle}">
                <TextBlock Style="{StaticResource BaseTextBlockStyle}"
                           Text="Wiki"
                           TextAlignment="Center"/>
            </Border>

            <Border Grid.Row="1"
                    Grid.Column="1"
                    Style="{StaticResource DetailsBorderStyle}"
                    HorizontalAlignment="Stretch"
                    VerticalAlignment="Stretch">
                <TextBox Style="{StaticResource DataTextBoxStyle}"
                         HorizontalAlignment="Stretch"
                         VerticalAlignment="Stretch"
                         Width="Auto"
                         Text="{Binding ShortDescription}"/>
            </Border>
        </Grid>

        <Grid Grid.Row="1">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition/>
            </Grid.RowDefinitions>

            <Border Grid.Row="0"
                    Grid.Column="1"
                    Style="{StaticResource BaseBorderStyle}"
                    HorizontalAlignment="Left"
                    Width="100">
                <TextBlock Style="{StaticResource BaseTextBlockStyle}"
                           Text="About"
                           TextAlignment="Center"/>
            </Border>

            <Border Grid.Row="1"
                    Grid.Column="1"
                    Style="{StaticResource DetailsBorderStyle}"
                    HorizontalAlignment="Stretch"
                    VerticalAlignment="Stretch">
                <TextBox Style="{StaticResource DataTextBoxStyle}"
                         HorizontalAlignment="Stretch"
                         VerticalAlignment="Stretch"
                         Width="Auto"
                         Text="{Binding DetailedDescription}"/>
            </Border>
        </Grid>

    </Grid>

    <Grid Grid.Column="1">
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>

        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>

        <Border Grid.Row="0"
                    Grid.Column="0"
                    Style="{StaticResource DetailsBorderStyle}"
                    HorizontalAlignment="Stretch">
            <TextBlock Style="{StaticResource BaseTextBlockStyle}"
                       Text="Title"
                       TextAlignment="Center"
                       HorizontalAlignment="Stretch"/>
        </Border>

        <Border Grid.Row="1"
                Grid.Column="0"
                Style="{StaticResource DetailsBorderStyle}"
                HorizontalAlignment="Stretch"
                VerticalAlignment="Stretch">
            <TextBox Style="{StaticResource DataTextBoxStyle}"
                     HorizontalAlignment="Stretch"
                     Text="{Binding Title}"/>
        </Border>

        <Border Grid.Row="2"
                Grid.Column="0"
                Style="{StaticResource DetailsBorderStyle}"
                HorizontalAlignment="Stretch">
            <TextBlock Style="{StaticResource BaseTextBlockStyle}"
                       Text="Author"
                       TextAlignment="Center"/>
        </Border>

        <Border Grid.Row="3"
                Grid.Column="0"
                Style="{StaticResource DetailsBorderStyle}"
                HorizontalAlignment="Stretch"
                VerticalAlignment="Stretch">
            <TextBox Style="{StaticResource DataTextBoxStyle}"
                     HorizontalAlignment="Stretch"
                     Text="{Binding Author}"/>
        </Border>

        <Border Grid.Row="4"
                Grid.Column="0"
                Style="{StaticResource DetailsBorderStyle}"
                HorizontalAlignment="Stretch">
            <TextBlock Style="{StaticResource BaseTextBlockStyle}"
                       Text="Quantity"
                       TextAlignment="Center"/>
        </Border>

        <Border Grid.Row="5"
                Grid.Column="0"
                Style="{StaticResource DetailsBorderStyle}"
                HorizontalAlignment="Stretch"
                VerticalAlignment="Stretch">
            <TextBox Style="{StaticResource DataTextBoxStyle}"
                     HorizontalAlignment="Stretch"
                     Text="{Binding Quantity}"/>
        </Border>

        <Border Grid.Row="0"
                Grid.Column="1"
                Style="{StaticResource DetailsBorderStyle}"
                HorizontalAlignment="Stretch">
            <TextBlock Style="{StaticResource BaseTextBlockStyle}"
                       Text="Buy Price"
                       TextAlignment="Center"/>
        </Border>

        <Border Grid.Row="1"
                Grid.Column="1"
                Style="{StaticResource DetailsBorderStyle}"
                HorizontalAlignment="Stretch"
                VerticalAlignment="Stretch">
            <TextBox Style="{StaticResource DataTextBoxStyle}"
                     HorizontalAlignment="Stretch"
                     Text="{Binding BuyPrice}"/>
        </Border>

        <Border Grid.Row="2"
                Grid.Column="1"
                Style="{StaticResource DetailsBorderStyle}"
                HorizontalAlignment="Stretch">
            <TextBlock Style="{StaticResource BaseTextBlockStyle}"
                       Text="Borrow Price"
                       TextAlignment="Center"/>
        </Border>

        <Border Grid.Row="3"
                Grid.Column="1"
                Style="{StaticResource DetailsBorderStyle}"
                HorizontalAlignment="Stretch"
                VerticalAlignment="Stretch">
            <TextBox Style="{StaticResource DataTextBoxStyle}"
                     HorizontalAlignment="Stretch"
                     Text="{Binding BorrowPrice}"/>
        </Border>

        <Button Grid.Row="5"
                Grid.Column="1"
                Style="{StaticResource SaveButtonStyle}"/>

        <Button Grid.Row="5"
                Grid.Column="1"
                Style="{StaticResource RemoveButtonStyle}"
                HorizontalAlignment="Right"/>
    </Grid>

</Grid>

使用这个我希望在列表视图中显示基于可观察集合的页面,从数据库中加载一些项目。 页面视图模型如下:

public class ManageItemsViewModel : BaseViewModel, IManageItemsViewModel
{
    public ManageItemsViewModel()
    {
        if(dalInterface == null)
        {
            dalInterface = ApplicationContext.Container.Resolve<IDalInterface>();
        }
        if(eventCenter == null)
        {
            eventCenter = ApplicationContext.Container.Resolve<IEventCenter>();
        }

        Items = new ObservableCollection<ItemViewModel>();
    }

    public ObservableCollection<ItemViewModel> Items { get; set; }

    public void Refresh()
    {
        var dalItems = dalInterface.GetAllItems();
        foreach(Item item in dalItems)
        {
            var vm = Items.Where(v => v.ID.Equals(item.ID));
            if(vm.Equals(null))
            {
                var newItemVm = (ItemViewModel)ApplicationContext.Container.Resolve<IItemViewModel>();
                newItemVm.SetData(item);
                Items.Add(newItemVm);
            }
        }
        NotifyPropertyChanged("Items");
    }

    public void LoadData()
    {
        if(Items.Count == 0)
        {
            var dalItems = dalInterface.GetAllItems();
            foreach(Item item in dalItems)
            {
                var newItemVm = (ItemViewModel)ApplicationContext.Container.Resolve<IItemViewModel>();
                newItemVm.SetData(item);
                Items.Add(newItemVm);
            }
            NotifyPropertyChanged("Items");
        }
        else
        {
            Refresh();
        }
    }

}

页面视图如下:

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition/>
    </Grid.RowDefinitions>

    <Button Grid.Row="0"
            Margin="2"
            Style="{StaticResource AddButtonStyle}"
            Click="GoToAddNewItem"/>

    <Button Grid.Row="0"
            Margin="2"
            HorizontalAlignment="Right"
            Style="{StaticResource CloseButtonStyle}"
            Click="GoToItems"/>

    <ListView Grid.Row="1"
              ItemsSource="{Binding Items, Mode=TwoWay}"
              Margin="5">
        <ListView.ItemTemplate>
            <DataTemplate>
                <templates:EditableItem/>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</Grid>

该页面应该是(目前我在数据库中只有一个项目用于测试): enter image description here

我现在遇到的问题是我无法在此项目模板中看到图像,尽管项目模板中的所有其他属性都正确显示。 我尝试使用图像路径,因为我从数据库中获取它并将源路径属性绑定到项目xaml,同时我尝试在项目VM中有一个ImageSource或BitmapImage属性,以使xaml图像源绑定到这个属性但到目前为止没有任何成功。

在阅读了很多关于并且一次又一次地尝试的问题之后我没有成功,我在这里...... 关于我做错的任何提示? 非常感谢!

(P.S。我正在努力的应用程序是一个UWP应用程序,可能很重要......)

2 个答案:

答案 0 :(得分:2)

您不能将Image控件用作另一个Image控件的Source属性的值。

改为使用ImageSource

private ImageSource image;
public ImageSource Image
{
    get { return image; }
    set
    {
        image = value;
        NotifyPropertyChanged("Image");
    }
}

并将GetImage方法更改为:

private ImageSource GetImage(string imagePath)
{
    return new BitmapImage(new Uri(imagePath, UriKind.RelativeOrAbsolute));
}

也就是说,你可以简单地删除Image属性并直接绑定到ImagePath。内置类型转换将自动从路径字符串转换为ImageSource。

<Image Source="{Binding ImagePath}"/>

另请注意,Mode=TwoWay对此绑定毫无意义。

答案 1 :(得分:0)

当我一次又一次地搜索这个问题并尝试了许多建议的解决方案时,我终于找到了一个适合我的解决方案并解决了这个问题。 我实现了一个小小的演示,以显示究竟是如何工作的。 UWP应用程序不仅限于与图片文件夹交互。可以从磁盘上的任意文件夹加载图像。 希望这会有助于其他人。

public class ViewModel : INotifyPropertyChanged
{
    public ViewModel()
    {
        PickFileCommand = new ActionCommand(PickFile, true);
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public ICommand PickFileCommand { get; set; }

    private BitmapImage imageSrc;
    public BitmapImage ImageSrc
    {
        get { return imageSrc; }
        set
        {
            imageSrc = value;
            NotifyPropertyChanged("ImgSource");
        }
    }

    private async void PickFile()
    {
        var filePicker = new FileOpenPicker
        {
            SuggestedStartLocation = PickerLocationId.PicturesLibrary
        };
        filePicker.FileTypeFilter.Add(".jpg");
        filePicker.FileTypeFilter.Add(".jpeg");
        filePicker.FileTypeFilter.Add(".png");

        StorageFile file = await filePicker.PickSingleFileAsync();

        if (file != null)
        {
            var stream = await file.OpenAsync(FileAccessMode.Read);
            var bitmap = new BitmapImage
            {
                UriSource = new Uri(file.Path, UriKind.Absolute)
            };
            await bitmap.SetSourceAsync(stream);

            ImageSrc = bitmap;
        }
    }

    protected void NotifyPropertyChanged(string name)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged.Invoke(this, new PropertyChangedEventArgs(name));
        }
    }
}

现在,解决图像问题的技巧是在类后面的View代码中。

 public sealed partial class MainPage : Page
{
    private ViewModel dataContext;
    public MainPage()
    {
        this.InitializeComponent();
        dataContext = new ViewModel();

        DataContext = dataContext;
    }

    **private void PageLoaded(object sender, RoutedEventArgs e)
    {
        if (DataContext is ViewModel dc)
        {
            dc.PropertyChanged += Dc_PropertyChanged;
        }
    }
    private void Dc_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
        if(e.PropertyName.Equals("ImgSource"))
        {
            if (DataContext is ViewModel dc)
            {
                ShowImage.Source = dc.ImageSrc;
            }
        }
    }**
}

需要的是要明确设置Image UI元素的源代码。我通过从ViewModel订阅PropertyChanged事件并设置图像源来实现这一点。