2017-09-19 10 views
0

これについて多くの質問があったことを知っています。私は多くを検索し、これについて見つけたすべてを試しましたが、動作させることはできません。 簡単に言えば、何らかの理由でListViewアイテムテンプレート内に画像を表示できません。バインディングリストビューアイテムテンプレート画像ObservableCollectionが動作しない

だから私はこの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> 

(現時点では、私が唯一のテストのためにDBに一つのアイテムを持っています) : enter image description here

私が今直面している問題は、このアイテムテンプレート内の画像は表示されませんが、他のすべてのプロパティはアイテムテンプレート内に正しく表示されています。 イメージパスをDBから取得して、xamlアイテムのソースパスプロパティをこれにバインドするときにイメージパスを使用しようとしましたが、アイテムVM内にImageSourceまたはBitmapImageプロパティを設定してxamlイメージソースをバインドしましたこれまでどんな成功もしていませんでした。

多くの質問を読んで、もう一度やり直してみたら、私はここにいます... 私が間違っていることについてのヒントはありますか? 多くの感謝!

+0

今後の質問のヒントとヒントとして、*あなたのコードをすべて*投稿しないでください。それを最小限に抑えて、関連する部分だけを表示してください。 – Clemens

+0

ヒントをお寄せいただきありがとうございます。次回は投稿する予定です。 –

答えて

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 code behind classです。

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イベントを購読し、画像ソースを設定することでこれを行いました。

1

あなたは別のImageコントロールのSourceプロパティの値として、Imageコントロールを使用することはできません(P.S.私が働いているアプリは...多分それは重要、UWPアプリです)。

利用代わりImageSource:言っ


private ImageSource GetImage(string imagePath) 
{ 
    return new BitmapImage(new Uri(imagePath, UriKind.RelativeOrAbsolute)); 
} 
が、あなたは、単に Imageプロパティを削除し、 ImagePathに直接結合することができます:

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

とにGetImage方法を変更します。組み込みの型変換は自動的にパス文字列からImageSourceに変換されます。

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

ということにも注意してくださいMode=TwoWayは、この結合のために意味をなさない。

+0

既に試しました...実際には、イメージソースをイメージパスにバインドする最初の実装でした。しかし、うまくいきませんでした。そのためImageSource、BitmapImageに行きました。その後、Image ... –

+0

ImagePathは単に無効です。あなたが掲示したそのコードの壁では伝えにくいです。実際にはImagePathを 'string.Empty'以外に設定することはありません。 – Clemens

+0

恐らく重要なのは、UWPアプリのファイルアクセス権限が限られていることです。 BitmapImageは、ファイルシステム内のどこからでもロードすることはできません。 [ファイルアクセス許可](https://docs.microsoft.com/en-us/windows/uwp/files/file-access-permissions)を参照してください。 – Clemens

関連する問題