Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Portal
  • |
  • Mitglieder
Beiträge von MillionsterNutzer
Thema: DataGrid: Daten bei großen Datenmengen dynamisch beim Scrollen nachladen
Am im Forum: GUI: WPF und XAML

Wow, das ist einiges an Input, da muss ich mich erst mal durchkämpfen...

Thema: DataGrid: Daten bei großen Datenmengen dynamisch beim Scrollen nachladen
Am im Forum: GUI: WPF und XAML

Hallo!

Ich habe in meiner Anwendung eine Ansicht in der der Nutzer ziemlich große Datenmengen in einem DataGrid ansehen kann. Da sind z.B. 10.000 Zeilen keine Seltenheit.
Aktuell wurde es so gelöst das über einen Count die Anzal aller verfügbaren Datensätz ermittelt wird und der Benutzer sich dann 'seitenweise' durchklicken kann.
Nehmen wir zum Beispiel an das pro Seite 50 Datensätze angezeigt werden dann hätten wir bei 10.000 Datensätz insgesamt 200 Seiten. Jedesmal wenn der Nutzer also zur nächsten Seite (oder eben einer bestimmten) springt dann werden von der Datenbank eben nur die 50 Datensätze abgefragt die tatsächlich benötigt werden. Das schont den Arbeitsspeicher und die Ladezeiten der Datenbank sind auch deutlich kürzer.

Nun wird gewünscht dass das Ganze etwas einfacher für den Nutzer werden soll und das bisherige System durch eines ersetzt werden soll dass die Daten dynamisch nachläd sobald der Benutzer die Scrollbar bedient.
Ich könnte wetten das ich nicht der erste bin der so ein Problem hat. allerdings konnte ich kein passendes Tutorial oder ähnliches finden?

Hat jemand von euch einen Tip oder eigene Erfahrungen mit dem Thema. Gibt es evtl. noch alternative Ansätze wie der Benutzer effizient durch große Datenmengen navigieren könnte?

Viele Grüße

Ralf

Thema: WPF Behavior: Eigener Even ähnlich ValueChanged für DependencyProperty
Am im Forum: GUI: WPF und XAML

Mangels besserer Ideen habe mich heute dazu durchgerungend mein Problem mit einem statischen Event zu lösen - das ist eigentlich ziemlich nahe an dem dran was ich gesucht habe und erspart mir zumindest das Dummy-DependencyProperty das ich in meinem ersten Ansatz noch hatte:


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Interactivity;

namespace CustomizableUserControlVisibility
{
    public delegate void VisibilityChangedEventHandler(object visibilityDictionary);

    public class WPFCustomVisibilityBehavior : Behavior<DependencyObject>
    {
        #region Fields
        public static event VisibilityChangedEventHandler OnVisibilityChanged;

        private Control _control = null;
        private ContextMenu _contextMenu;
        private bool _contextMenuIsBuilt = false;
        #endregion

        #region Properties
        public bool AllowCustomVisibility
        {
            get { return (bool)GetValue(AllowCustomVisibilityProperty); }
            set { SetValue(AllowCustomVisibilityProperty, value); }
        }

        public static readonly DependencyProperty AllowCustomVisibilityProperty = DependencyProperty.Register("AllowCustomVisibility", typeof(bool), typeof(WPFCustomVisibilityBehavior), new PropertyMetadata(false));

        public string VisibilityGroupName
        {
            get { return (string)GetValue(VisibilityGroupNameProperty); }
            set { SetValue(VisibilityGroupNameProperty, value); }
        }

        public static readonly DependencyProperty VisibilityGroupNameProperty = DependencyProperty.Register("VisibilityGroupName", typeof(string), typeof(WPFCustomVisibilityBehavior), new PropertyMetadata(string.Empty));

        public Dictionary<string, bool> VisibilityDictionary
        {
            get { return (Dictionary<string, bool>)GetValue(VisibilityDictionaryProperty); }
            set { SetValue(VisibilityDictionaryProperty, value); }
        }

        public static readonly DependencyProperty VisibilityDictionaryProperty = DependencyProperty.Register("VisibilityDictionary", typeof(Dictionary<string, bool>), typeof(WPFCustomVisibilityBehavior), new PropertyMetadata(new Dictionary<string, bool>()));
        #endregion

        #region Constructor
        public WPFCustomVisibilityBehavior()
        {
            OnVisibilityChanged += VisibilityChanged;
        }
        #endregion

        #region Overrrides
        protected override void OnAttached()
        {
            base.OnAttached();

            if (this.AllowCustomVisibility == false)
            {
                return;
            }

            this._control = this.AssociatedObject as Control;

            if (!string.IsNullOrEmpty(this.VisibilityGroupName) && this._control != null)
            {
                if (this.VisibilityDictionary.ContainsKey(this.VisibilityGroupName))
                {
                    if (this.VisibilityDictionary[this.VisibilityGroupName])
                    {
                        this._control.Visibility = Visibility.Visible;
                    }
                    else
                    {
                        this._control.Visibility = Visibility.Collapsed;
                    }
                }
                else
                {
                    this.VisibilityDictionary.Add(this.VisibilityGroupName, this._control.Visibility == Visibility.Visible ? true : false);
                }
            }

            // Add a ContextMenu to the Control, but only if it does not already have one (TextBox brings its default ContextMenu for copy, cut and paste)
            if (this._control != null && this._control.ContextMenu == null && !(this._control is TextBox))
            {
                this._contextMenu = new ContextMenu();
                ContextMenuService.SetContextMenu(this._control, this._contextMenu);
                this._control.ContextMenuOpening += (sender, e) => { ContextMenuOpening(e); };
            }
        }
        #endregion

        #region Event handling
        private void ContextMenuOpening(ContextMenuEventArgs e)
        {
            if (this._contextMenuIsBuilt == false)
            {
                // Clear Items just to be sure there is nothing in it...
                this._contextMenu.Items.Clear();

                // Create default items first
                MenuItem showAll = new MenuItem() { Header = "Show all optional fields", IsCheckable = false, FontWeight = FontWeights.Bold };
                showAll.Click += MenuItem_ShowAll_Click;
                MenuItem hideAll = new MenuItem() { Header = "Hide all optional fields", IsCheckable = false, FontWeight = FontWeights.Bold };
                hideAll.Click += MenuItem_HideAll_Click;

                // Create field items and sort them by name
                Dictionary<string, MenuItem> menuItems = new Dictionary<string, MenuItem>();
                foreach (string k in this.VisibilityDictionary.Keys)
                {
                    MenuItem menuItem = new MenuItem() { Header = k, Name = k, IsCheckable = true, StaysOpenOnClick = true };
                    menuItem.Click += MenuItem_Click;

                    menuItems.Add(k, menuItem);
                }
                var keyList = menuItems.Keys.ToList();
                keyList.Sort();

                // Now add default items followed by field items
                this._contextMenu.Items.Add(showAll);
                this._contextMenu.Items.Add(hideAll);
                this._contextMenu.Items.Add(new Separator());

                foreach (string key in keyList)
                {
                    this._contextMenu.Items.Add(menuItems[key]);
                }

                this._contextMenuIsBuilt = true;
            }

            foreach (Object o in this._contextMenu.Items)
            {
                MenuItem mi = o as MenuItem;

                if (mi != null && mi.FontWeight != FontWeights.Bold)
                {
                    mi.IsChecked = this.VisibilityDictionary[mi.Name];
                }
            }
        }

        private void MenuItem_Click(object sender, RoutedEventArgs e)
        {
            MenuItem mi = sender as MenuItem;

            if (mi != null && this.VisibilityDictionary != null && this.VisibilityDictionary.ContainsKey(mi.Name))
            {
                this.VisibilityDictionary[mi.Name] = mi.IsChecked;

                OnVisibilityChanged(this.VisibilityDictionary);
            }
        }

        private void MenuItem_HideAll_Click(object sender, RoutedEventArgs e)
        {
            List<string> keys = this.VisibilityDictionary.Keys.ToList<string>();

            foreach (string key in keys)
            {
                this.VisibilityDictionary[key] = false;
            }

            OnVisibilityChanged(this.VisibilityDictionary);
        }
        private void MenuItem_ShowAll_Click(object sender, RoutedEventArgs e)
        {
            List<string> keys = this.VisibilityDictionary.Keys.ToList<string>();

            foreach (string key in keys)
            {
                this.VisibilityDictionary[key] = true;
            }

            OnVisibilityChanged(this.VisibilityDictionary);
        }

        private void VisibilityChanged(object visibilityDictionary)
        {
            if (this._control != null && this.VisibilityDictionary != null && this.VisibilityDictionary == visibilityDictionary && !string.IsNullOrEmpty(this.VisibilityGroupName))
            {
                if (this.VisibilityDictionary.ContainsKey(this.VisibilityGroupName))
                {
                    if (this.VisibilityDictionary[this.VisibilityGroupName])
                    {
                        this._control.Visibility = Visibility.Visible;
                    }
                    else
                    {
                        this._control.Visibility = Visibility.Collapsed;
                    }
                }
            }
        }
        #endregion
    }
}

Ich dachte ich poste das mal hier, falls mal jemand ein ähnliches Problem hat...

Thema: WPF Behavior: Eigener Even ähnlich ValueChanged für DependencyProperty
Am im Forum: GUI: WPF und XAML

Der Hintergrund ist eben auch der dass ich eben mehrere Formulare mit vielen Feldern habe. Wenn ich da in jedem ViewModel für jedes Feld ein extra Property habe was ich ggf. dann auch noch separat speichern würde... das würde ganz schön in Fleißarbeit ausarten.
Mir scheint das Behavior hier einiges (wenn auch bei weitem nicht alles) an Arbeit abzunehmen.
Das Konfigurationsmodell lass ich hier mal aussen vor: Das angesprochene Dictionary welches für jedes Feld die Sichtbarkeit bereithält wird im ViewModel als Property bereitgestellt und im Model in XMl serialisiert/deserialisiert (benutzerbezogen). Da habe ich gar kein Problem.

Ich könnte auch einfach ein zusätzliches Dummy-Property in dem Behavior hinzufügen auf welches ich dann einen ValueChanged-Event setze. Wenn also Ein Feld an oder abgewählt wird könnte ich dieses Dummy-Property ändern und alle anderen würden mitbekommen dass sie nochmal in das Dictionary schauen müssen on sich ihr Zustand geändert hat. Würde funktionieren, scheint mir aber mehr nicht der richtige Weg zu sein.

Thema: WPF Behavior: Eigener Even ähnlich ValueChanged für DependencyProperty
Am im Forum: GUI: WPF und XAML

Hi!

Sorry für die nichtssagende Überschrift, aber ich weiß schlichtweg nicht wie das heißt has ich suche, daher muss ich hier leider etwas ausholen:

In meiner Anwendung gibt es mehrere Formulare welche meistens nach dem selben Schema aufgebaut sind: Für jeden Wert den der Nutzer bearbeiten kann gibt es ein Label mit einer Überschrift und eine TextBox (oder Ähnlich) um den eigentlichen Wert zu ändern.
Die neue Anfoderung ist es nun das der Nutzer die Möglichkeit bekommen soll einzelne Werte ausblenden zu können (nicht jeder Kunde benutzt alle Felder).

Um dieses Problem felxibel zu lösen würde ich gerne ein Behavior verwenden welches ich an alle Controls hängen kann die ausgeblendet werden sollen. Dieses Behavior besteht hauptsächlich aus zwei Properties: Einen Gruppennamen der bei allen Controls gleich ist welche zusammen gehören (also z.B. ein Label mit der Überschrift + die zugehörige Textbox). Außerdem ein Dictionary welches für alle Gruppennamen eines Formulars einen bool-Wert bereit hält welcher die Sichtbarkeit steuern soll.
Innherhalb des Behaviors wird für jedes Control ein ContextMenü angelegt mit dem man eine Übersicht aller Gruppen bekommt und mit dem man einzelne Gruppen an- und abwählen, also sichtbar und unsichtbar machen kann.

Das Ganze funktioniert auch inzwischen bis zu dem Punkt an dem der Benutzer im Kontextmenü eine Gruppe an- oder abwählt. An dieser Stelle müssen nun eigentlich alle Controls getriggert werden so dass sie das Dictionary mit den Gruppennamen nochmals prüfen ob sich ihr Zustand geändert hat. Ich suche also sowas wie einen Event konnte aber im Netz nicht herausfinden wie sowas auszusehen hat. Im Prinzip würde mir reichen wenn mir jemand ein gutes Stichwort gibt oder ein passendes Tutorial verweist.

Hier noch der Code meines Behavior mit einem TODO an der entsprechenden Stelle:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Interactivity;

namespace CustomizableUserControlVisibility
{
    public class WPFCustomVisibilityBehavior : Behavior<DependencyObject>
    {
        #region Fields
        private Control _control = null;
        private ContextMenu _contextMenu;
        private bool _contextMenuIsBuilt = false;
        #endregion

        #region Properties
        public bool AllowCustomVisibility
        {
            get { return (bool)GetValue(AllowCustomVisibilityProperty); }
            set { SetValue(AllowCustomVisibilityProperty, value); }
        }

        public static readonly DependencyProperty AllowCustomVisibilityProperty = DependencyProperty.Register("AllowCustomVisibility", typeof(bool), typeof(WPFCustomVisibilityBehavior), new PropertyMetadata(false));

        public string VisibilityGroupName
        {
            get { return (string)GetValue(VisibilityGroupNameProperty); }
            set { SetValue(VisibilityGroupNameProperty, value); }
        }

        public static readonly DependencyProperty VisibilityGroupNameProperty = DependencyProperty.Register("VisibilityGroupName", typeof(string), typeof(WPFCustomVisibilityBehavior), new PropertyMetadata(string.Empty));

        public Dictionary<string, bool> VisibilityDictionary
        {
            get { return (Dictionary<string, bool>)GetValue(VisibilityDictionaryProperty); }
            set { SetValue(VisibilityDictionaryProperty, value); }
        }

        public static readonly DependencyProperty VisibilityDictionaryProperty = DependencyProperty.Register("VisibilityDictionary", typeof(Dictionary<string, bool>), typeof(WPFCustomVisibilityBehavior), new PropertyMetadata(new Dictionary<string, bool>()));
        #endregion

        #region Constructor

        #endregion

        #region Overrrides
        protected override void OnAttached()
        {
            base.OnAttached();

            if (this.AllowCustomVisibility == false)
            {
                return;
            }

            this._control = this.AssociatedObject as Control;

            if (!string.IsNullOrEmpty(this.VisibilityGroupName) && this._control != null)
            {
                if (this.VisibilityDictionary.ContainsKey(this.VisibilityGroupName))
                {
                    if (this.VisibilityDictionary[this.VisibilityGroupName])
                    {
                        this._control.Visibility = Visibility.Visible;
                    }
                    else
                    {
                        this._control.Visibility = Visibility.Collapsed;
                    }
                }
                else
                {
                    this.VisibilityDictionary.Add(this.VisibilityGroupName, this._control.Visibility == Visibility.Visible ? true : false);
                }

                // Add a ContextMenu to the Control, but only if it does not already have one (TextBox brings its default ContextMenu for copy, cut and paste)
                if (this._control.ContextMenu == null && !(this._control is TextBox))
                {
                    this._contextMenu = new ContextMenu();
                    ContextMenuService.SetContextMenu(this._control, this._contextMenu);
                    this._control.ContextMenuOpening += (sender, e) => { ContextMenuOpening(e); };
                }
            }
        }
        #endregion

        #region Event handling
        private void ContextMenuOpening(ContextMenuEventArgs e)
        {
            if (this._contextMenuIsBuilt == false)
            {
                this._contextMenu.Items.Clear();

                Dictionary<string, MenuItem> menuItems = new Dictionary<string, MenuItem>();

                foreach (string k in this.VisibilityDictionary.Keys)
                {
                    MenuItem menuItem = new MenuItem() { Header = k, Name = k, IsCheckable = true, StaysOpenOnClick = true };
                    menuItem.Click += MenuItem_Click;

                    menuItems.Add(k, menuItem);
                }

                var keyList = menuItems.Keys.ToList();
                keyList.Sort();

                foreach (string key in keyList)
                {
                    this._contextMenu.Items.Add(menuItems[key]);
                }

                this._contextMenuIsBuilt = true;
            }

            foreach (MenuItem mi in this._contextMenu.Items)
            {
                mi.IsChecked = this.VisibilityDictionary[mi.Name];
            }
        }

        private void MenuItem_Click(object sender, RoutedEventArgs e)
        {
            MenuItem mi = sender as MenuItem;

            this.VisibilityDictionary[this.VisibilityGroupName] = mi.IsChecked;

            //TODO: Let all suscribing controls know that the Visibility for a group was changed in the VisibilityDictionary => this should call GroupVisibilityWasChanged()...
        }

        private void GroupVisibilityWasChanged()
        {
            if (this.VisibilityDictionary[this.VisibilityGroupName])
            {
                this._control.Visibility = Visibility.Visible;
            }
            else
            {
                this._control.Visibility = Visibility.Collapsed;
            }
        }
        #endregion
    }
}

Thema: Etikettendesigner mit WPF entwickeln: Wo anfangen?
Am im Forum: GUI: WPF und XAML

Ich denke der WPF Designer war schon mal ein sehr guter Hinweis. Ich werde versuchen mich da mal weiter einzuarbeiten.

Ich hätte auch den Report Designer von DevEx zur Verfügung. Ich bin mir aber nicht sicher ob ich da nicht mit Kanonen auf Spatzen schießen würden. Werde mal meinen Kollegen darauf ansprechen der für die Reports zuständig ist...

Vielen, vielen Dank für den Input. Wie schon gesagt: Ich denke das sollte als Starthilfe genügen.

VG

Ralf

Thema: Etikettendesigner mit WPF entwickeln: Wo anfangen?
Am im Forum: GUI: WPF und XAML

Hi,

eine meiner nächsten Aufgaben wird das Ablösen eines altes Etikettendesigners für die hauseigenen Etikettiergeräte meines Arbeitgebers sein. Der alte Designer basiert noch auf C++ und ist sehr aufwending zu warten außerdem kann in unserem Team kaum noch jemand C++.

Der Untersatz des Designers wird die hausinterne Rendering-Engine der Auszeichner sein. Dieser Engine füttere ich einfach ein Etikettenlayout auf dem irgendwelche Bild- oder Textfelder sind und ich bekomme als Ergebnis ein Bild welches dem späteren Etikett entspricht.

Meine Aufgabe wird es also nun sein über dieses 'Etikettenbild' welches ich von der Renderingengine bekomme einen designer darüber zu legen welches dem Benutzer erlaubt die unterschiedlichen Felder auf dem Etikett zu verschieben, editieren, kopieren, anlegen, löschen, ...etc.

Nun bin ich mir nicht sicher wie ich die Aufgabe am besten angehen soll und wollte mir erst mal irgendwelche ähnliche Lösungen oder Tutorials im Netz ansehen musste nun allerdings feststellen das ich entweder die falschen Begriffe beim Suchen verwende oder aber es sowas nicht all zu oft gibt.

Kann mir jemand von euch passende Artikel, Bibliotheken oder einfach nur Tipps dazu geben?

VG

Ralf

Thema: System.Windows.Interactivity.dll wird blockiert beim compilieren
Am im Forum: Entwicklungs- und Laufzeitumgebung (Infrastruktur)

Hallo xxxprod,

du hast mich in die richtige Richtung geschickt: Obwohl ich die dll gelöscht habe lief der Service noch tadellos hoch was mich doch schwer gewundert hat. Ich habe dann die 'Common Language Runtime Excecptions' im Service-Projekt mal wieder auf 'Thrown' gesetzt um zu schauen ob es vielleicht doch irgendwie kracht und ob ich es einfach nicht mitbekomme und tatsächlich:
Es war eine DLL die über MEF dynamisch hinzugeladen wird welche die besagte System.Windows.Interactivity.dll verwendet!

Ich werde die MEF assembly vorerst mal weg löschen da ich diese für meine Arbeit nicht brauche. Das löst mein Problem mal temporär. Zusätzlich werd ich mal den zuständigen Kollegen befragen ob seine MEF assembly tatsächlich die Interactivity braucht.

Vielen Dank für den Denkanstoss!!!!

VG

Ralf

Thema: System.Windows.Interactivity.dll wird blockiert beim compilieren
Am im Forum: Entwicklungs- und Laufzeitumgebung (Infrastruktur)

Hi!

Ich habe aktuell zwei Solutions die ihre Assemblies in das gleiche Ausgabeverzeichnis hinein erstellen. Bei der ersten Solution geht es um einen Windowsdienst bei der zweiten um eine GUI die unter anderem auch mit dem Dienst kommuniziert.

Während das in den letzten Wochen meist gut funktioniert hat, bekomme ich in den letzten Tagen beim erstellen der GUI-Solution nun immer die Meldung:

Fehler
Error 15 Could not copy "C:\Libraries\baseline\Source\Common\packages\MvvmLightLibs.4.2.30.0\lib\net45\System.Windows.Interactivity.dll" to "..\..\..\Binaries\System.Windows.Interactivity.dll". Exceeded retry count of 10. Failed.

Und tatsächlich ist die dll auch gesperrt da sie genutzt wird. Seltsam ist aber das sie von der Service-Solution genutzt wird welche ich in der Regel immer nebenher im Debugger laufen lasse. Mir leuchtet dabei nicht ein warum meine WindowsService-Solution eben die System.Windows.Interactivity.dll nutzen sollte da sie quasi keine Oberfläche hat und genau darum geht es ja in der besagten DLL. Ich finde mit der Suchfunktion von VS auch keinerlei Hinweis auf die System.Windows.Interactivity.dll innerhalb meiner Service-Solution.
Ich finde es auch etwas ominös dass ich meine Service-Solution erstellen kann während die GUI läuft, aber ich kann nicht die GUI-Solution erstellen während die Service-Solution läuft.

Wie kann ich rausfinden welcher Teil meiner Service-Solution tatsächlich die System.Windows.Interactivity.dll nutzt und blockiert?

VG

Ralf

Thema: WPF: Benutzerelemente innerhalb von Grid-Spalte sollen nur so groß (breit) werden wie notwendig
Am im Forum: GUI: WPF und XAML

Hallo Parso,

danke für den Hinweis: Das habe ich nicht bedacht dass das Alignment standardmäßig auf stretch steht! Genau das habe ich gesucht! Danke!

@witte: Um ein Haar wäre ich deinem Vorschalg gefolgt, da ich eben auch keine andere Lösung sah...

Viele Grüße

Ralf

Thema: WPF: Benutzerelemente innerhalb von Grid-Spalte sollen nur so groß (breit) werden wie notwendig
Am im Forum: GUI: WPF und XAML

Bin mir nicht sicher ob du das richtig verstehst: Es handelts sich quasi um ein Grid mit zwei Spalten: Die erste für die Feldnamen, die zweite Spalte für die Eingabefelder für die Datenfelder. Also Quasi so


<Grid>
  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="Auto" />
    <ColumnDefinition Width="*" />
  </Grid.ColumnDefinitions>

Die Eingabefelder (also Text-, Check- und Combobox) in der zweiten Spalte bekommen also weit aus mehr Platz in der Breite als sie eigentlich benötigen würden... Für Text- und Combobox nicht weiters schlimm, aber für die CheckBox eben wie zuvor beschrieben nicht so doll.
Width und MaxWidth der CheckBox auf einen festen Wert setzen mag ich nicht (wegen Übersetzungen). Und der Wert Auto hat in diesem Szenario wohl keine Auswirkung.

OK?

VG

Ralf

Thema: WPF: Benutzerelemente innerhalb von Grid-Spalte sollen nur so groß (breit) werden wie notwendig
Am im Forum: GUI: WPF und XAML

Hallo zusammen,

ich habe einige WPF basierte Formulare. Dabei sind alle Eingabefelder wie üblich innerhalb eines <Grid> Elements damit die Feldnamen und die eigentlichen Eingabefelder schön ausgerichtet und auch immer gleich breit sind.
Mein Problem ist nun das ich neben Combo- und TextBoxen auch eine CheckBox habe die in dem Grid genauso breit gemacht wird wie die Spalte hergibt. Das führt dazu das der User nun rechts neben dem Text der Checkbox ins scheinbar 'Leere' klicken kann und sich dann trotzdem noch der Status der Checkbox ändert.
Für mich als Entwickler ist das klar: Die Checkbox hört eben nicht da auf wo ihr Text aufhört sondern erst da wo die Spalte aufhört. Für den User ist das aber leider nicht nachzuvollziehen.

Gibt es eine einfache Möglichkeit der CheckBox zu sagen das sie nur so groß werden soll wie nötig?

Viele Grüße

Ralg

Thema: WPF / MVVM: Animation im Fortschrittsfenters läuft nicht
Am im Forum: GUI: WPF und XAML

Hi Rioma,

oh man du hast natürlich Recht, ich konnte heute Morgen wohl noch nicht klar denken: Die Operation muss auf jeden Fall in einem Backgroundworker ausgeführt werden damit die UI nicht einfriert. Erst nachdem der Backgroundworker gestartet wurde kann ich das ProgressWindow model anzeigen. Wenn der BackgroundWorker fertig ist wird auch die Message zum Schließen des ProgressWindow verschickt und es geht weiter.
So passt das alles...

Evtl. nicht wirklich das was du gemeint hast, aber du hast mich in die richtige Richtung geschubst.

Viele Grüße

Ralf

Thema: WPF / MVVM: Animation im Fortschrittsfenters läuft nicht
Am im Forum: GUI: WPF und XAML

Hallo zusammen,

ich habe für zeitintensive Operationen in meiner Anwendung ein kleines ProgressWindow dass ich immer vor der eigentlichen Operation öffne und danach wieder verschwinden lasse. Das Öffnen geschieht aus dem ViewModel heraus indem ich eine Message an mein Hauptfenster schicke. Das Schließen geschieht ebenfalls über eine Message die direkt an das ProgressWindow geht damit dieses sich selber schließt.

Das hat bisher eigentlich immer einwandfrei funktioniert weil im ProgressWindow eigentlich nur ein statisches Bild und ein einfaches 'Operation XYZ wird ausgeführt... Bitte warten Sie... ' angezeigt wurde.

Nun wurde aber gewünscht das sich da was drehen soll, damit der Benutzer nicht glaubt es wär alles abgestürtzt und hier wird es nun schwierig für mich. Ich habe also eine Animation (Storyboard) für das Bild erstellt welches dieses dreht. Auch das funktioniert noch einwandfrei wenn ich das ProgressWindow nur so zum testen anzeige, wenn aber tatsächlich im Hintergrund der UI-Thread mit der eigentlichen Arbeit beschäftigt ist dann bleibt damit auch meine Animation stehen.

Ich dachte erst kurz daran die zeitintensive Operation in einen separaten Thread zu packen, allerdings muss der Benutzer tatsächlich darauf warten, es ist also egal ob ich diese direkt im UI-Thread ausführe oder dieser dann auf die Beendigung des separaten Threads wartet.

Wenn ich das ProgressWindow in einem separten Thread ausführe komme ich scheinbar ebenfalls dem UI-Thread in die Quere:


        private void ReceiveMessage(OpenProgressWindowMessage action)
        {
            // This will show the dialog but the animation is not executed
            //Common.Controls.ProgressWindow wnd = new Common.Controls.ProgressWindow(this._openProgressWindowMessageAction.TitleText, this._openProgressWindowMessageAction.ShowProgressTextBox, this._openProgressWindowMessageAction.InitialProgressText, this._openProgressWindowMessageAction.ShowAnimatedIcon);
            //wnd.Show();

            this._openProgressWindowMessageAction = action;

            // This will cause an exception asking for an STA thread
            //Task.Factory.StartNew(() => { this.OpenProgressWindow(); });

            // This will not show anything at all
            //Thread progressWindowThread = new Thread(() => this.OpenProgressWindow());
            //progressWindowThread.SetApartmentState(ApartmentState.STA);
            //progressWindowThread.Start();

            // This will also cause an exception asking for an STA thread
            BackgroundWorker bgWorker = new BackgroundWorker();
            bgWorker.DoWork += ProgressWindow_DoWork;
            bgWorker.WorkerSupportsCancellation = false;
            bgWorker.WorkerReportsProgress = false;
            bgWorker.RunWorkerAsync();
        }

        private void ProgressWindow_DoWork(object sender, DoWorkEventArgs e)
        {
            Common.Controls.ProgressWindow wnd = new Common.Controls.ProgressWindow(this._openProgressWindowMessageAction.TitleText, this._openProgressWindowMessageAction.ShowProgressTextBox, this._openProgressWindowMessageAction.InitialProgressText, this._openProgressWindowMessageAction.ShowAnimatedIcon);
            wnd.Show();
        }

        private void OpenProgressWindow()
        {
            Common.Controls.ProgressWindow wnd = new Common.Controls.ProgressWindow(this._openProgressWindowMessageAction.TitleText, this._openProgressWindowMessageAction.ShowProgressTextBox, this._openProgressWindowMessageAction.InitialProgressText, this._openProgressWindowMessageAction.ShowAnimatedIcon);
            wnd.Show();
        }

Irgendwie komme ich grade nicht weiter... Kann mir jemand einen Tip geben was ich falsch mache?

VG

Ralf

Thema: Prüfen ob ScrollBar notwendig bzw. alle Items sichtbar?
Am im Forum: GUI: WPF und XAML

OK, also wenn ich das Problem auf die harte Tour löse, dann sieht das so aus:


        private void FindListViewItems(DependencyObject obj, List<ListViewItem> listViewItems)
        {
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
            {
                DependencyObject child = VisualTreeHelper.GetChild(obj, i);

                if (child != null && child is ListViewItem)
                {
                    listViewItems .Add (child as ListViewItem);
                }
                else
                {
                    FindListViewItems(child, listViewItems);
                }
            }
        }

        private void ComponentGroupListView_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            List<ListViewItem> listViewItems = new List<ListViewItem>();
            this.FindListViewItems(this.ComponentGroupListView, listViewItems);

            double requiredWidth = 0;
            foreach (ListViewItem i in listViewItems)
            {
                requiredWidth += i.ActualWidth + i.Margin.Left + i.Margin.Right;
            }

            if (requiredWidth > this.ComponentGroupListView .ActualWidth )
            {
                this.ScrollGrid.Visibility = System.Windows.Visibility.Visible;
            }
            else
            {
                this.ScrollGrid.Visibility = System.Windows.Visibility.Collapsed;
            }
        }

Das funktioniert scheinbar einwandfrei - ist allerdings alles andere als elegant. Falls jemand noch eine schönere Idee hat, dann bitte her damit. Ansonsten wirds so wohl schon gehen.

VG

Ralf

Thema: Prüfen ob ScrollBar notwendig bzw. alle Items sichtbar?
Am im Forum: GUI: WPF und XAML

Hallo ThomasE,

sorry wegen der späten Antwort, war die letzten Tage ausser Gefecht...

damit du dir besser vorstellen kannst was ich da treibe habe ich einen Screenshot von dem Menü gemacht um welches es mir geht. Da sieht man auch auf der rechten Seite zwei Buttons mit denen man scrollen kann.

Der Code der beiden Buttons ist denkbar einfach. Ich ermittle den ScrollViewer meiner ListView und rufe dann deren PageLeft() oder PageRight() Methode auf:

        
        private void ScrollLeftButton_Click(object sender, RoutedEventArgs e)
        {
            ScrollViewer myScrollviewer = FindVisualChild<ScrollViewer>(this.ComponentGroupListView);
            if (myScrollviewer != null)
            {
                myScrollviewer.PageLeft();
            }
        }

Hier noch das XAML des ListView:

                <ListView x:Name="ComponentGroupListView"
                          Grid.Column="0"
                          Margin="0"
                          VerticalContentAlignment="Center"
                          Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"
                          BorderThickness="0"
                          DisplayMemberPath="DisplayName"
                          ItemsSource="{Binding AvailableComponentGroups}"
                          ScrollViewer.HorizontalScrollBarVisibility="Disabled"   
                          ScrollViewer.VerticalScrollBarVisibility="Disabled"
                          SelectedValue="{Binding Path=SelectedComponentGroup,
                                              Mode=TwoWay}"
                          SelectionMode="Single"
                          SizeChanged="ComponentGroupListView_SizeChanged">
                    <ListView.ItemContainerStyle>
                        <Style BasedOn="{StaticResource ComponentGroupListItemStyle}"
                               TargetType="ListViewItem">
                            <Setter Property="VerticalAlignment"
                                    Value="Center" />
                            <Setter Property="VerticalContentAlignment"
                                    Value="Center" />
                        </Style>
                    </ListView.ItemContainerStyle>
                    <ListView.ItemsPanel>
                        <ItemsPanelTemplate>
                            <StackPanel Orientation="Horizontal" />
                        </ItemsPanelTemplate>
                    </ListView.ItemsPanel>
                </ListView>

Das Problem ist wie bereits erwähnt, dass die Buttons aktuell immer sichtbar sind, auch wenn die ListView genug Platz hat und es nichts zu scrollen gibt.
Daher wüsste ich gern wie ich im CodeBehind mitbekommen kann wann ich die Buttons einblenden oder aber ausblenden kann.

VG

Ralf

Thema: Prüfen ob ScrollBar notwendig bzw. alle Items sichtbar?
Am im Forum: GUI: WPF und XAML

Hi ThomasE,

es handlet sich um eine Eigenproduktion :-)

VG

Ralf

Thema: Prüfen ob ScrollBar notwendig bzw. alle Items sichtbar?
Am im Forum: GUI: WPF und XAML

Hallo!

In meiner Anwendung ist das Navigationsmenü dynamisch, so das der User evtl. wenig oder viele Bereiche in der Anwendung hat die er ansehen darf. Wenn er nun zusätzlich das Window recht klein hält kann es dazu kommen das nicht mehr alle Menüpunkte angezeigt werden. Aktuell sind die Menüpunke in einer horizontalen ListView gesammelt. Eigentlich gibt es schon ein zusätzliches kleines PopUp-Menü mit welchem der User immer alle Menüeinträge erreichen kann.
Dennoch wurde nun gefordert das es eine Möglichkeit geben soll das eigentliche Menü zu scrollen. Allerdings soll es kein Einfacher horizontaler Scrollbalken sein - da der ja bei einem Menü nicht all zu toll aussieht.

Tatsächlich habe ich nun zwei kleine fesche Buttons die genau das tun was geforer wurdet, allerdings sind diese aktuell immer sichtbar - auch wenn evtl. gar nicht gescrollt werden müsste.

Wie kann ich von meiner ListView erfahren ob nun gerade genug Platz da ist um alle Elemente komplett anzuzeigen oder nicht?
Ich hab inzwischen schon zwei Stunden rumprobiert und bekomms trotzdem einfach nicht hin.

Kann mir jemand kurz einen Tip geben?

Viele Grüße

Ralf

Thema: ResourceDictionary wird mehrmals geladen?
Am im Forum: GUI: WPF und XAML

Hallo StefanS83,

ich bin überrascht das du an einen Thread anknüpfst der bereits seit über einem halben Jahr erledigt war.

Ich kann dir sagen das bei meinem Projekt das SharedResourceDictionary einwandfrei funktioniert und auch ich VS2013 nutze. Im Designer verhält es sich nicht anders als das einfache ResourceDictionary. Ich nutze den VS-Designer nur um eine grobe Vorschau zu bekommen wie das Ganze zur Laufzeit aussieht und auch das stimmt meines Erachtens zu über 90%.

Der Einzige Unterschied zwischen den beiden ist ja, dass das SharedResourceDictionary eine art Singleton ist und es eben nur einmal geladen wird und anschließend von den unterschiedlichsten Windows und Controls gemeinsam genutzt wird, während das klassische ResourceDictionary mehrmals instanziert wird.

Mir ist an dieser Stelle nicht ganz klar warum eurer Meinung nach beim SharedResourceDictionary ein unterschied zum klassischen hinsichtlich der Nutzung von StaticResources und DynamicResources sein sollte. Meines Erachtens sollte das bei beiden Dictionaries gleich ablaufen.

VG

Ralf

Thema: Bestimmte Controls einer Anwendung gleichschalten?
Am im Forum: GUI: WPF und XAML

Hi!

Ich habe in meiner Anwendung mehrere Ansichten welche jeweils aus unterschiedlichen Assemblies kommen. Alle dieser Ansichten haben ein Ribbon-Control oben drauf - aus Sicht des Nutzers is es immer das selbe Ribbon nur ändert sich je nach Ansicht eben der Inhalt. Aus Anwendungssicht haben die Ribbons nur ein gemeinsames Style ansonsten sind diese komplett unabhängig voneinander.
Nun habe ich festgestellt das man das Ribbon durch einen Doppelklick auf einen Tabheader minimieren kann. Das Problem dabei ist dass in diesem Fall nur ein Ribbon minimiert ist - alle anderen bekommen davon leider nix mit. Damit wird es für den Benutzer nun inkonsistent.

Kennt jemand von euch eine Möglichkeit ohne großen Aufwand das IsMinimized-Property aller meiner Ribbons gleich zu schalten? Evtl. über den Style oder ein gemeinsames ResourceDictionary?

Viele Grüße

Ralf

Thema: Änderung an dynamic resource in ResourceDictionary von UserControls nicht bemerkt?
Am im Forum: GUI: WPF und XAML

hi ProGamer,

Hmm, ich komm nicht drauf wie das funktionieren soll:

Ich habe ja bereits ein Syle namens CaptionLabel. Diesen weise ich eben jedem Label zu welches eine Überschrift sein soll. Da ich das entsprechende RessourceDictionary schon im XAML meiner Windows uns UserControls definiert habe wird auch im Cider bereits die richtige Formattierung angezeigt.
Der von dir genannt Style wird dann wohl eher zur Laufzeit erstellt und im CodeBehind zugewiesen, richtig?

VG

Ralf

Thema: Änderung an dynamic resource in ResourceDictionary von UserControls nicht bemerkt?
Am im Forum: GUI: WPF und XAML

Hallo jogibear9988, Hi MrSparkle,

Das x:Shared-Attribut ist in meinem Fall, wenn ich die Doku recht verstanden habe, nicht geeignet. Ich habe auch kurz versucht dieses einzusetzen allerdings ohne Erfolg.

MrSparkles Vorschlag leuchtet mir nicht ganz ein: Zwar könnte ich wohl die Farbe über das Konfigurationsmodell speichern, aber wie binde ich diese dann an die Hintergrundfarbe aller meiner 'CaptionLabels' ohne dabei für jedes Element explizit ein Binding angeben zu müssen?

Viele Grüße

Ralf

Thema: Änderung an dynamic resource in ResourceDictionary von UserControls nicht bemerkt?
Am im Forum: GUI: WPF und XAML

Hallo Parso,

vorweg muss ich wohl noch einge Dinge zu meinem Problem erwähnen die ich Heute herausbekommen:

1. Meine SharedResourceDictionary Klasse hat bisher als Key value die Uri zur Resource verwendet. Dabei hat sich herausgestellt das eine andere Schreibweise dazu führt das ein neuer Eintrag im Dictionary gemacht wird. Die beiden Uris

"pack://application:,,,/Common.Themes;component/Controls.xaml"
und
"pack://application:,,,/Common.Themes;component/CONTROLS.xaml"

führen also dazu das auf unterschiedliche ResourceDictionaries verwiesen würde.
Tatsächlich hatte ich dieses Problem in meinem Code auch. Nachdem ich meine SharedResourceDictionary-Klasse also etwas toleranter gemacht habe bekomme ich nun etwas konstantere Ergebnisse.

2. Der Weg über "Application.Current.Resources" scheint mir nur innerhalb eines begrenzten Bereichs zu funktionieren (Ich vermute mal das es nur innerhalb eines Windows oder einer Assembly zu greifen scheint, was für mich leider nicht ausreichen ist).

3. Wie bereits ursprünglich erwähnt ist der Weg über "this.Resources" für mich nicht tragbar.

Ich habe mich also dafür entschieden meinen CaptionLabelBrush-Wert zu manipulieren indem ich das ResourceDictionary über meine SharedResourceDictionary-Klasse abgreife. Dabei ist mir nun jedoch aufgefallen dass ich hier den Wert nur ändern kann wenn das ResourceDictionary noch nicht 'verwendet' wurde. Das heißt ich kann den Wert also nur einmal beim Initialisieren meiner Anwenung setzen. Danach hat die Änderung keine Auswirkung mehr.
Wenn ich nun versuche den Farbwert des SolidColorBrush zu überschreiben anstatt den ganzen Brush zu tauschen dann klappt das auch nur beim ersten mal - danach is das IsFrozen-Property des Brush auf true und ich kann nichts mehr daran ändern.

Das ist alles was ich soweit in Erfahrung bringen konnte. Im schlimmsten Fall werd ich es dabei belassen müssen - ich kann nicht ganze Tage investieren um ein paar Farben zur Laufzeit zu ändern. Aber falls jeman hier noch eine Idee wie man das Problem noch in den Griff bekommen könnte...

Viele Grüße

Ralf

Thema: Änderung an dynamic resource in ResourceDictionary von UserControls nicht bemerkt?
Am im Forum: GUI: WPF und XAML

Hallo!

Ich würde meinem Benutzer gern die Möglichkeit geben einige Farben in der GUI zu ändern. Ich dachte dabei dass es mit Dynamic Resouces am einfachsten geht, habe aber momentan noch Probleme. Hier mein Aufbau:

Ich habe ein ResourceDictionary für Farben welches in der Datei Colors.xaml enthalten ist. In diesem ResourceDictionary habe ich den SolidColorBrush 'CaptionLabelBrush' definiert.
In einem weiteren ResourceDictionary welches in der Datei Controls.xaml enthalten ist habe ich ein Style für Labels namens 'CaptionLabel' definiert welches als Background den zuvor genannten SolidColorBrush als DynamicResource verwendet. Damit das geht wurde im zweiten ResourceDictionary das erste als MergedDictionary angegeben.

In meiner inzwischen recht komplexen Oberfläche wird nun an vielen unterschiedlichen Stellen das Controls-ResourceDictionary als MergedDictionary verwendet. Dies wäre zwar zur Laufzeit eigentlich nicht nötig da es ja vom Window nach unten and UserControls durchgereicht wird, allerdings sieht sonst im Cider die Vorschau gänzlich falsch aus.
Die verwendeten UserControls aber auch das Controls-ResourceDictionary stammen aus separaten Projekten bzw. dlls.
Das einbinden der MergedDictionaries erfolgt mit Hilfe einer eigenen SharedResourceDictionary Klasse welche sicherstellt das ein und das selbe ResourceDictionary nicht mehrmals von unterschiedlichen UserControls neu geladen und instanziert wird. Es sollte folglich in der ganzen Anwendung nur eine Instanz des Controls-ResourceDictionary geben welches von allen Windows/UserControls genutzt wird.

Nun war mein Ziel das der Benutzer die Farbe die im CaptionLabelBrush definiert ist zur Laufzeit ändern kann damit im Anschluß alle CaptionLabels die neue Farbe erhalten. Das seltsame ist dass das auch funktioniert, aber nicht überall gleich: Je nachdem wie und wo ich in meinem Code das ResourceDictionary zu erreichen versuche wird die Änderung sichtbar oder scheinbar ignoriert. Folgende Möglichkeiten konnte ich ausfindig machen:


SharedResourceDictionary controlsResDict = new SharedResourceDictionary();
controlsResDict.Source = new Uri("pack://application:,,,/Common.Themes;component/Controls.xaml");
if (controlsResDict Resources.Contains("CaptionLabelBrush"))
{
   controlsResDict ["CaptionLabelBrush"] = theNewBrush;
}

if (this.Resources.Contains("CaptionLabelBrush"))
{
    this.Resources["CaptionLabelBrush"] = theNewBrush;
}

if (Application.Current.Resources.Contains("CaptionLabelBrush"))
{
    Application.Current.Resources["CaptionLabelBrush"] = theNewBrush;
}

Leider hängt es scheinbar davon ab wo ich die Änderung durchführe um damit erfolgreich zu sein (App.xaml.cs oder ViewModel oder auch direkt inm CodeBehind). Auch hatte ich teilweise das Phänomen das manche UserControls die neue Frabe erhielten und andere nicht, obgleich diese jeweils auf der gleichen Ebene standen jedoch aus unterschiedlichen dlls kamen.
Letztlich scheint mir nur der Weg über 'this.Resources' zuverlässig zu sein allerdings ist dieser auch am Aufwendigsten da dies direkt im CodeBehind zu geschehen hat und dies ein ernsthaftes Verteilungsproblem darstellt.

Hat jemand von euch eine Idee oder einen Hinweis was ich falsch mache bzw. wie man das richtig angeht?
Hat jemand von euch so ein Szenario bereits erfolgreich gelöst?

Viele Grüße

Ralf

Thema: ResourceDictionary wird mehrmals geladen?
Am im Forum: GUI: WPF und XAML

Hallo Coffeebean! Hallo Parso!

Danke für den Hinweis! Mit dem SharedResourceDictionary sollte es klappen!

Werd mich dann mal an die Arbeit machen - Danke für die Hilfe!

VG

Ralf

Thema: ResourceDictionary wird mehrmals geladen?
Am im Forum: GUI: WPF und XAML

Hallo!

Meine Anwendung wird inzwischen ziemlich komplex und hat viele Windows und UserControls in verschiedenen Dateien. Damit am Ende alles einheitlich aussieht gibt es ein großes XAML-ResourceDictionary das alle Styles und teilweise auch XAML-Bilder enthält - dieses ResourceDictionary wird momentan noch in jedem Window und UserControl explizit angegeben, damit ich zur DesignZeit schon wenigstens eine grobe Vorstellung davon bekomme wie meine Arbeit nachher aussieht und ich nicht Unmengen von "The resource 'xyz' could not be resolved." Meldungen in meiner ErrorList angezeigt bekomme.
Nun musste ich feststellen das zur Laufzeit tatsächlich jedes UserControl ein und das selbe ResourceDictionary einliest, obgleich dies in den meisten Fällen gar nicht notwendig wäre da das richte ResourceDictionary bereits vom übergeordneten Element weitergegeben würde. Leider wirkt sich das inzwischen ziemlich in den Ladezeiten beim Starten der Anwendung aus so dass ich nun wirklich etwas unternehmen muss.

Kennt jemand dieses Problem und weiß einen Rat? Könnte ich evtl. die ResourceDictionaries nur zur Designzeit einbinden?

Viele Grüße

Ralf

Thema: Binding an Dependency Property von UserControl
Am im Forum: GUI: WPF und XAML

Hi Robin0,

habs mit deinem Hinweis hinbekommen:

IsReadOnly="{Binding Path=ReadOnly, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"

Vielen Dank für die Hilfe!!!

Ralf

Thema: Binding an Dependency Property von UserControl
Am im Forum: GUI: WPF und XAML

Hallo zusammen,

ich habe gerade ein UserControl erstellt welches es erlauben soll einen bestimmten Objekttyp anzuzeigen und zu editieren. Momentan sind das testhalber nur einige TextBoxen welche eben bestimmte Properties des zugewiesenen Objekts anzeigen.
Nun habe ich dem UserControl ein DependencyProperty ReadOnly hinzugefügt welches ich neben dem anzuzeigenden Objekt setzen will. Das funktioniert soweit auch, allerdings frage ich mich nun wie ich das ReadOnly meines UserControls an die ReadOnly Properties der enthaltenen Textboxen weiterleiten kann.

Kann mich da jemand bitte eben in die richtige Richtung leiten? Irgendwie habe ich beim googlen bei diesem Thema kein Glück (bzw. die falschen Suchbegriffe).

VG

Ralf

Thema: WPF ComboBox: Selektion anhand Tastatureingabe?
Am im Forum: GUI: WPF und XAML

Hi ProGamer,

das stimmt dann könnte der nutzer aber nicht mehr die 104 eintippen. Beide Eingaben sollten zum gleichen Ergebnis führen.

VG

Ralf

Thema: WPF ComboBox: Selektion anhand Tastatureingabe?
Am im Forum: GUI: WPF und XAML

Hallo zusammen,

ich habe eine etwas ungewöhliche Anforderung für eine Combobox:
Die besagte ComboBox ist nicht editierbar dient also lediglich zur Selektion von Werten. Angeziegt werden in der dieser Box Artikel und zwar in Form von "Artikelnr - Artikelname". Als Beispiel wäre die folgende Liste denkbar:

101 - Milch
102 - Mehl
103 - Butter
104 - Salz
105 - Safran
...

Nun kann der Benutzer ja standardmäßig das 'Salz' auswählen indem er die '104' auf der Tastatur eintippt. Allerdings würde ich dem Benutzer gerne auch erlauben durch eintippen von 'Salz' das gewünschte Item selektiert zu bekommen.
Es soll kein Filter ausgefürhrt werden - lediglich eine Selektion.

Ich will das Rad nicht unnötig neu erfinden, allerdings habe ich im Netz nichts passendes gefunden...

Hatte jemand von euch schon mal eine ähnliche Anforderung und kann mir eine gute Herangehensweise aufzeigen?

Viele Grüße

Ralf