none
Converter-Klasse und Zugriff auf Control aus MainWindow.xaml RRS feed

  • Frage

  • Hallo allerseits,

    Ich binde mehrere Controls (Checkboxen, Textboxen...) an Properties einer eigenen Klasse, die INotifyPropertyChanged implementiert.
    Das funktioniert auch.
    Nun möchte ich eine Eigenschaft eines ListView-Controls (SelectedIndex) an eine neue Propertiy ("Kundennummer)" binden.
    Der SelectedIndex soll sich aus der Suche nach einem betimmten Item-wert (Kundennummer) bilden, die in der neuen Property gehalten werden soll.
    Dazu könnte ich ja einen Converter implementieren, der sich zwischen Property und der gebundenen Control-Eigenschaft SelectedIndex schaltet.
    Nun habe ich begonnen, eine Converter-Klasse zu implementieren, und möchte in dessen Convert()-Methode mit dem ListView-Control arbeiten (,um den Eintrag zu suchen).
    Aber: Fehler: das Control ist "im aktuellen Kontext nicht vorhanden".

    Wie kann ich in der Converter-Klasse auf das ListView-Control zugreifen? Oder gibt es einen geschickteren Weg?

    Viele Grüße

    Wolfgang
    Donnerstag, 10. Januar 2019 09:00

Antworten

  • Hi Wolfgang,
    vermutlich ist Dir die Notwendigkeit und Wirkungsweise eines IValueConverters nicht ausreichend klar. Eine Klasse, die IValueConverter implementiert, wird hat zwei Methoden, in denen Werte hin- und wieder zurück konvertiert werden. Die Instanz solch einer Klasse (üblicherweise implizit aus einer Ressource) wird genutzt, um eine Eigenschaft im Oberflächen-Element an eine Eigenschaft im "Untergrund" (z.B. im ViewModel bei MVVM oder auch im Hintergrund-Code des Windows) zu binden. Solch ein Konverter ist vor allem dann erforderlich, wenn sich die Typen der Eigenschaften unterschieden. Die Rück-Konvertierung ist in diesem Einsatzfall nur dann erforderlich, wenn das Oberflächen-Element Eingaben erlaubt, die dann in die gebundene Eigenschaft konvertiert werden sollen.

    Wenn Du etwas anderes wünschst, dann beschreibe mal etwas genauer, was Du suchst.


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP für Developer Technologies)
    Meine Homepage mit Tipps und Tricks

    Donnerstag, 17. Januar 2019 10:42

Alle Antworten

  • Hi,

    ich habe noch nicht ganz geblickt, auf was du hinaus möchtest.. 

    Um einen Eintrag in einer ListView zu suchen, gibt es viele Möglichkeiten. Ich habe mal etwas aus einem Projekt raus-extrahiert:

    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Linq;
    using System.Windows.Data;
    using GalaSoft.MvvmLight;
    
    namespace TestFilter
    {
        public class TestViewModelClass : ViewModelBase
        {
            public TestViewModelClass()
            {
                DeineCollection = new ObservableCollection<DeinModel>();
            }
    
            public ObservableCollection<DeinModel> DeineCollection { get; set; }
            CollectionViewSource cvsDeineCollectionViewSource;
            public ICollectionView View
            {
                get
                {
                    if (cvsDeineCollectionViewSource == null)
                    {
                        cvsDeineCollectionViewSource = new CollectionViewSource();
                        cvsDeineCollectionViewSource.Source = DeineCollection;
                    }
                    return cvsDeineCollectionViewSource.View;
                }
            }
    
            private DeinModel selectedEntry;
            public DeinModel SelectedEntry
            {
                get { return selectedEntry; }
                set
                {
                    Set(ref selectedEntry, value);
                }
            }
    
            private string filterItems;
            public string FilterItems
            {
                get { return filterItems; }
                set
                {
                    Set(ref filterItems, value);
                    ExecuteApplyFilter();
                }
            }
    
            private string filterGroups;
            public string FilterGroups
            {
                get { return filterGroups; }
                set
                {
                    Set(ref filterGroups, value);
                    ExecuteApplyFilter();
                }
            }
    
            private void ExecuteApplyFilter()
            {
    
                criteria.Clear();
    
    
                if (!string.IsNullOrEmpty(FilterItems))
                {
                    criteria.Add(new Predicate<DeinModel>(x => x.Itemtitle.ToLower().Contains(FilterItems.ToLower())));
                }
                if (!string.IsNullOrEmpty(FilterGroups))
                {
                    criteria.Add(new Predicate<DeinModel>(x => x.Itemgroup.ToLower().Contains(FilterGroups.ToLower())));
                }
    
                cvsDeineCollectionViewSource.View.Filter = dynamic_Filter;
    
            }
    
            private List<Predicate<DeinModel>> criteria = new List<Predicate<DeinModel>>();
    
            private bool dynamic_Filter(object item)
            {
                DeinModel p = item as DeinModel;
                bool isIn = true;
                if (criteria.Count() == 0)
                    return isIn;
                isIn = criteria.TrueForAll(x => x(p));
    
                return isIn;
            }
    
        }
    
        public class DeinModel
        {
            private string _itemtitle;
            private string _itempath;
            private string _itemgroup;
    
            public string Itempath { get => _itempath; set => _itempath = value; }
            public string Itemgroup { get => _itemgroup; set => _itemgroup = value; }
            public string Itemtitle { get => _itemtitle; set => _itemtitle = value; }
        }
    }
    


    So werden dir nur die Einträge angezeigt, die seinen Suchkriterien entsprechen.

    Wenn du einen Eintrag selektieren möchtest, kannst du das (z.B.) so machen:

            private void SelectItem(string Kundennummer)
            {
                var res = DeineCollection.Where(s => s.Itempath == Kundennummer).FirstOrDefault();
                if (res != null)
                {
                    SelectedEntry = res;
                };
            }

    Das LV ist eigentlich simpel (bis auf dein Datatemplate):

    <ListView Name="lvIrgendwas" SelectionMode="Single"
    		  ItemsSource="{Binding View}"
    		  SelectedItem="{Binding SelectedEntry, Mode=TwoWay}">
    		  ...
    		  ...
    		  ...

    Nutzt du das MVVM Entwurfsmuster? Meine Code-Schnipsel stammen aus einem Projekt mit MVVMLight, sollte aber kein Problem sein etwas anzupassen (die Properties zB.).

    Gruß

    Stefan


    Freiberufler im Bereich Softwareentwicklung Von der PLC und Robotik zu VB.NET & C#, vorrangig WPF und UWP

    Donnerstag, 10. Januar 2019 10:49
  • Hallo, Danke für die einstweilige Antwort.

    MVVM benutzte ich bisher gar nicht.

    Ich erkläre es nochmal kurz bildlich:
    "Links" in Speicher: Kundennummer
    "Rechts" in Anzeige: SelectedIndex
    "Dazwischen:" eine "Umrechnung" hin und her.
    Für das "Dazwischen" will ich einen Converter benutzen. Soweit gut.
    Im Konverter brauche ich aber für die Umrechnung das ListView-Control (s. o. "Anzeige")!
    Wie man mit dem ListView Enträge Einträge sucht, ist nicht der Knackpunkt, sondern der Zugriff auf das ListView Control überhaupt selbst.

    Hier habe ich schon mal einen Ansatz probiert: schon mal interessant
    WpfHowTo: Pass and use a Control in it's own ValueConverter for Convert/Convert​Back
    es wird aber da nicht ganz mein Fall abgebildet, deswegen bin ich noch nicht weitergekommen.

    Ich persönlich möchte nur einen Wert hin- und herrechnen, und das Control ist immer nur "Beiwerk", wird aber für beide Umrechnungsrichtungen benötigt.

    Gruß Wolfgang


    Donnerstag, 17. Januar 2019 08:54
  • Hi Wolfgang,
    vermutlich ist Dir die Notwendigkeit und Wirkungsweise eines IValueConverters nicht ausreichend klar. Eine Klasse, die IValueConverter implementiert, wird hat zwei Methoden, in denen Werte hin- und wieder zurück konvertiert werden. Die Instanz solch einer Klasse (üblicherweise implizit aus einer Ressource) wird genutzt, um eine Eigenschaft im Oberflächen-Element an eine Eigenschaft im "Untergrund" (z.B. im ViewModel bei MVVM oder auch im Hintergrund-Code des Windows) zu binden. Solch ein Konverter ist vor allem dann erforderlich, wenn sich die Typen der Eigenschaften unterschieden. Die Rück-Konvertierung ist in diesem Einsatzfall nur dann erforderlich, wenn das Oberflächen-Element Eingaben erlaubt, die dann in die gebundene Eigenschaft konvertiert werden sollen.

    Wenn Du etwas anderes wünschst, dann beschreibe mal etwas genauer, was Du suchst.


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP für Developer Technologies)
    Meine Homepage mit Tipps und Tricks

    Donnerstag, 17. Januar 2019 10:42