Laden...

[erledigt] TextBox Binding an ListViewItem Objekt

Erstellt von Rioma vor 9 Jahren Letzter Beitrag vor 9 Jahren 4.287 Views
R
Rioma Themenstarter:in
228 Beiträge seit 2013
vor 9 Jahren
[erledigt] TextBox Binding an ListViewItem Objekt

Hallo,

ich erkläre euch mal kurz mein vorhaben:

Ich habe eine ListView, diese ist an ein Objekt gebunden. Das ganze sieht so aus:


<ListView  Grid.Row="1" Grid.Column="0" MinHeight="75" Width="305" Foreground="Black" Name="ListSongs">
            <ListView.View>
                <GridView>
                    <GridViewColumn Width="210" Header="Song" DisplayMemberBinding="{Binding Name}"/>
                    <GridViewColumn Width="65" Header="Genre" DisplayMemberBinding="{Binding Genre}"/>
                </GridView>
            </ListView.View>
            <ListView.ItemContainerStyle>
                <Style TargetType="{x:Type ListViewItem}">
                    <Setter Property="ToolTip" Value="{Binding Path=Content}"/>
                </Style>
            </ListView.ItemContainerStyle>
            <ListView.ContextMenu>
                <ContextMenu>
                    <MenuItem Header="Delete" Click="ListSongsDelete_Click"/>
                    <MenuItem Header="Play" Click="ListSongsPlay_Click"/>
                    <MenuItem Header="Stop" Click="ListSongsStop_Click"/>
                </ContextMenu>
            </ListView.ContextMenu>
        </ListView>

Nun habe ich noch mehrere Felder, die ich an das ausgewählte Objekt in der ListView binden möchte, dass heißt wenn ich ein anderes Item auswähle, werden die anderen Felder aktualisiert.
Leider habe ich seit stunden Probleme damit.


 <TextBox Text="{Binding ElementName=ListSongs, Path=<-- Hier das Objekt + Eigenschaft -->}"/>

Könnte mir von euch vielleicht jemand auf die Sprünge helfen?

Danke euch!

692 Beiträge seit 2008
vor 9 Jahren

Hallo Rioma,

hab mit ListView noch nicht gearbeitet, aber klappt das nicht?


 <TextBox Text="{Binding ElementName=ListSongs, Path="{SelectedItem.Eigenschaft}"/>

Schöne Grüße
Quaneu

R
Rioma Themenstarter:in
228 Beiträge seit 2013
vor 9 Jahren

Danke schonmal, aber
genauso hatte ich es versucht, vielleicht mache ich auch noch wo anders einen Fehler.
Die ListView hängt an einer CollectionView mit Filtermöglichkeit. Gefüttert wird die CollectionView von einer List<T> wobei T das Objekt ist.
Jemand schon erfahrung damit gemacht?

692 Beiträge seit 2008
vor 9 Jahren

Hmmm...

Hätte noch zwei Vorschläge:

  1. CollectionView hat ein Property CurrentItem. Wenn man sich an das bindet?
  2. Vielleicht klappt es mit IsSynchronizedWithCurrentItem="True" auch mit SelectedItem

Leider sind dies nur sehr wage Vorschläge.

Schöne Grüße
Quaneu

P
157 Beiträge seit 2014
vor 9 Jahren

Hallöchen,

also erstmal :

  1. werden in deinem Listview die Elemente korrekt angezeigt, die aus deiner Datenquellen kommen ?
  2. Wenn ja...probier doch mal SelectedValue ... SelectedItem kann auch ein Frameworkelement sein, dass dein Element visualisiert(ListViewItem). Da klappt dann naturlich auch das Binding gegen eine gesuchte Objekteigenschaft nicht ...

Wenn mal ein Binding-Fehler auftritt, schau in die Ausgabe, da stehen meist Fehlermeldungen mit denen man mehr anfangen kann als mit :"klappt nicht" 😃

Bei Binding-Fehler irgendwas mit :error 40 : Binding Path not found... da steht dann auch in der langen Fehlermeldung der Typ gegen den du das Binding gesetzt hast.

Wenn das nicht hilft müsstest du etwas mehr posten, da ich so nur raten kann.

vg

Wenn's zum weinen nicht reicht, lach drüber!

R
Rioma Themenstarter:in
228 Beiträge seit 2013
vor 9 Jahren

Danke euch, es klappt nun mit:

 <TextBox Text="{Binding ElementName=ListSongs, Path=SelectedValue.Name}"/>

Er sagt mir nur im Designer: > Fehlermeldung:

Cannot resolve propertie Name in DataContext of type object.

Irgendjemand ne ahnung warum er meckert?

Hier der relevante C# Code


 private void CmdSongsHinzufügen_OnClick(object sender, RoutedEventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Multiselect = true;

            if (ofd.ShowDialog() == true)
            {
                mBand = new List<MusicBand>();

                foreach (var fileName in ofd.FileNames)
                {
                    
                    using (TagLib.File file = TagLib.File.Create(fileName))
                    {
                        mBand.Add(new MusicBand(file, fileName));
                    }
                }

                ListSongs.ItemsSource = MusicSongs.MSongs;
                CollectionView view = (CollectionView)CollectionViewSource.GetDefaultView(ListSongs.ItemsSource);
                
                view.Filter = MusicFilter;
            }
        }

        private bool MusicFilter(object item)
        {
            if (String.IsNullOrEmpty(TxtFilter.Text))
                return true;
            else
                return ((item as MusicSongs).Name.IndexOf(TxtFilter.Text, StringComparison.OrdinalIgnoreCase) >= 0);
        }

        private void TxtFilter_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
        {
            CollectionViewSource.GetDefaultView(ListSongs.ItemsSource).Refresh();
        }

2.207 Beiträge seit 2011
vor 9 Jahren

Irgendjemand ne ahnung warum er meckert?

Hallo Rioma,

ja, weil das SelectedItem zur Design-Zeit nicht gesetzt ist (vermute ich). Mein Tipp: Lass den Designer ganz weg. Du schreibst schöneren XAML-Code, weisst was er tut und andere tun das auch, wenn sie ihn sehen. Du nach 3 Wochen auch noch 😉. Ausserdem lädt VS schneller (je nach Grösse der View).

Gruss

Coffeebean

R
Rioma Themenstarter:in
228 Beiträge seit 2013
vor 9 Jahren

Danke das wird warscheinlich das Problem sein. Also ich Klicke mir meine GUI nicht zusammen, ich schreibe den XAML Code und habe darüber sofort das Ergebnis. Deswegen sprach ich vom Designer 😃

2 Fragen haben sich jetzt aber leider noch aufgetan:

1)
Alle Felder werden nun aktualisiert, soabalb ich ein anderes Item ausgewählt habe. Nur meine ImageSource nicht.

So sieht mein Xaml Code aus:


 <Image  DockPanel.Dock="Right" Height="125" Source="{Binding ElementName=ListSongs, Path=SelectedValue.SongCover}">
                        <Image.ContextMenu>
                            <ContextMenu>
                                <MenuItem Header="Entfernen" Click="CoverEntfernen_Click"/>
                            </ContextMenu>
                        </Image.ContextMenu>
                    </Image>

und hier der C# code:


   try
            {
                TagLib.IPicture p = _tagLibFile.Tag.Pictures[0];
                string coverPath = "Image/" + _tagLibFile.Tag.FirstAlbumArtist + "/" + _tagLibFile.Tag.Album + "/Cover.jpg";

                if (!Directory.Exists("Image/" + _tagLibFile.Tag.FirstAlbumArtist + "/" + _tagLibFile.Tag.Album))
                    Directory.CreateDirectory("Image/" + _tagLibFile.Tag.FirstAlbumArtist + "/" + _tagLibFile.Tag.Album);

                if (!System.IO.File.Exists(coverPath))
                    System.IO.File.WriteAllBytes(coverPath, p.Data.Data);

                this.SongCover = new BitmapImage(new Uri(coverPath, UriKind.Relative));
            }
            catch { }

Das mit dem Cover rausziehen und extern speichern funktioniert übrigens und der Pfad stimmt natürlich auch. Beachte ich bei der ImageSource irgendetwas nicht?

Wenn ich per per



        private void CoverHinzufügen_Click(object sender, RoutedEventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();

            if (ofd.ShowDialog() == true)
            {
                _albumImage = new BitmapImage(new Uri(ofd.FileName));
                MusicSongs mSong = (MusicSongs)ListSongs.SelectedValue;
                mSong.SongCover =  _albumImage;
            }

        }

Das Cover hinzufüge, wird es in der Gui sofort geladen.

2)
Deswegen auch meine 2te Frage, wie bekommt die Gui mit, dass ich etwas am Objekt geändert habe? Auch wenn ich in den Textboxen etwas änder, wird es sofort in die ListView übernommen.

Ich habe inotifypropertychanged nicht implementiert und eigentlich, ist dass doch ein KO Kriterium oder nicht?

2.207 Beiträge seit 2011
vor 9 Jahren

Ich habe inotifypropertychanged nicht implementiert und eigentlich, ist dass doch ein KO Kriterium oder nicht?

Ja, das ist es. Implementier es und schmeiss das Event.

Gruss

Coffeebean

R
Rioma Themenstarter:in
228 Beiträge seit 2013
vor 9 Jahren

Wie gesagt ich habe es getestet. Es funktioniert aus irgendeinem Grund auch ohne, ich habe mir einen Haltepunkt im Setter gesetzt und Sobald ich in der TextBox (SongName) etwas änder, und in der ListView das Item wechsel, springt er in den Setter und ändert die Eigenschaft.


using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using File = TagLib.File;

namespace MusicBox
{
    public class MusicSongs
    {
        public static List<MusicSongs> MSongsTemp = new List<MusicSongs>();

        private TagLib.File _tagLibFile;

        private string _songName;

        public string SongName
        {
            get { return _songName; }
            set { _songName = value; } //HALTEPUNKT
        }
      
        public string SongGenre { get; set; }
        public string SongInterpret { get; set; }
        public string SongYear { get; set; }
        public TimeSpan SongTime { get; set; }
        public ImageSource SongCover { get; set; }

        public string SongKind { get; set; }
        public DateTime SongDateAdded { get; set; }
        public string SongContent { get; set; }
        public string SongPath { get; set; }



        public MusicSongs(File tagLibFile, string path)
        {
            _tagLibFile = tagLibFile;
            SongPath = path;
            FillProperties();
            MSongsTemp.Add(this);
        }

        private void FillProperties()
        {
            SongName = _tagLibFile.Tag.Title;
            SongGenre = _tagLibFile.Tag.FirstGenre;
            SongYear = _tagLibFile.Tag.Year.ToString(CultureInfo.InvariantCulture);
            SongTime = _tagLibFile.Properties.Duration;
            SongKind = SongPath.Substring(SongPath.Length - 4, 4);
            SongInterpret = _tagLibFile.Tag.FirstAlbumArtist;
            SongDateAdded = DateTime.Now;

            try
            {
                TagLib.IPicture p = _tagLibFile.Tag.Pictures[0];
                string coverPath = "Image/" + _tagLibFile.Tag.FirstAlbumArtist + "/" + _tagLibFile.Tag.Album + "/Cover.jpg";

                if (!System.IO.File.Exists(coverPath))
                {

                    if (!Directory.Exists("Image/" + _tagLibFile.Tag.FirstAlbumArtist + "/" + _tagLibFile.Tag.Album))
                        Directory.CreateDirectory("Image/" + _tagLibFile.Tag.FirstAlbumArtist + "/" +
                                                  _tagLibFile.Tag.Album);

                    System.IO.File.WriteAllBytes(coverPath, p.Data.Data);
                }

                this.SongCover = new BitmapImage(new Uri(coverPath, UriKind.Relative));
            }
            catch { }

            SongContent = "Published: " + SongYear + Environment.NewLine +
           "Time: " + Math.Round(SongTime.TotalMinutes, 2) + " min " + Environment.NewLine +
           "Kind: " + SongKind;
        }
    }
}

Ist natürlich unpraktisch, wenn man immer erst das Item wechseln muss, aber es wäre auch unpraktisch, wenn ich inotifypropertychanged implementiere und die Eigenschaft 2 mal geändert wird, obwohl 1 mal reicht.

Hat jemand eine Idee woran es liegt?

Edit: Sorry, es reicht wenn ich aus der Textbox rausgehe. Es wird dann die Eigenschaft gesetzt. Wenn ich inotifypropertychanged implementiere, macht es keinen unterscheid. Es wird nur einmal gesetzt. Sehr komisch...

Edit2: Könnte daran liegen, das der DefaultWert vom UpdateSourceTrigger bei Textboxen LostFocus ist und nicht PropertyChanged, oder?

5.658 Beiträge seit 2006
vor 9 Jahren

Hi Rioma,

Sobald ich in der TextBox (SongName) etwas änder, und in der ListView das Item wechsel, springt er in den Setter und ändert die Eigenschaft.

Ja, das tut es.

Allerdings wird die Benutzeroberfläche dann nicht über die Änderung informiert und daher nicht aktualisiert. Bitte belies dich in der Doku über Sinn und Zweck des INotifyPropertyChanged-Ereignisses und beachte bitte die Hinweise der anderen Benutzer.

Bitte beachte auch in Zukunft [Hinweis] Wie poste ich richtig? , besonders Punkt 1 ("Erst suchen und in die Doku schauen, dann posten" und "Nicht nach Grundlagen fragen") und 8 ("Tut, worum man euch bittet").

Christian

Weeks of programming can save you hours of planning

R
Rioma Themenstarter:in
228 Beiträge seit 2013
vor 9 Jahren

Das sind alles wichtige hinweise, aber wie bereits gesagt, wird meine GUI aktualisiert und deswegen war ich so verwundert.

Eine CollectionView wird gefüttert mit einer List<T>, die CollectionView hängt an einer ListView.
Dann gibt es Textboxen, die an der SelectedValue.Eigenschaft hängen.
Sobald ich hier aktualsiere und die Textbox den Focus verliert, wird die Eigenschaft gesetzt und die ListView akktualisiert. Alles ohne INotifyPropertyChanged.