Laden...

[gelöst] MVVM - Listbox-Selektierung per Button aufheben

Erstellt von Lector vor 14 Jahren Letzter Beitrag vor 14 Jahren 10.928 Views
L
Lector Themenstarter:in
862 Beiträge seit 2006
vor 14 Jahren
[gelöst] MVVM - Listbox-Selektierung per Button aufheben

Hallo,

Ich habe eine MVVM-Anwendung in der ich das mit dem Code-Behind bisher immer etwas locker gesehen habe. Da ich gerade etwas Zeit habe wollte ich mal etwas unnötiges Code-Behind entfernen.
Ich habe jedoch ein Problem bei folgendem Szenario:

Ich habe eine Listbox in der ich Objekte anzeige.
Rechts davon befindet sich eine Detailansicht zum selektieren Element.
In dieser Detailansicht gibt es einen Close-Button. Dieser soll die Selektierung die ListBox aufheben. Dadurch wird die Detailansicht unsichtbar.
Momentan habe ich das per Click-Handler und einer C#-Zeile realisiert.

Hier ein kurzer Code-Überblick:


<ListBox Name="list" .../>
<ContentControl DataContext="{Binding ElementName=list,Path=SelectedItem}">
            <ContentControl.Template>
                <ControlTemplate TargetType="{x:Type ContentControl}">
                    <ControlTemplate.Triggers>
                        <Trigger Property="DataContext" Value="{x:Null}">
                            <Setter Property="Visibility" Value="Collapsed"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                    <Button Content="{DynamicResource CloseIcon}" IsCancel="True" Click="btnCloseDetails_Click"/><!--Hier sollte die Selektierung aufgehoben werden-->
                </ControlTemplate>
            </ContentControl.Template>
        </ContentControl>


private void btnCloseDetails_Click(object sender, RoutedEventArgs e)
    {
      list.SelectedIndex = -1;
    }

Meine Frage ist nun wie ich das ohne C#-Code realisieren könnte. Trigger funktionieren mit einem normalen Button ja nicht da beim Click keine Eigenschaft gesetzt wird und in EventTriggern kann ich nur Storyboard-Aktionen machen.

U
1.578 Beiträge seit 2009
vor 14 Jahren

ganz einfach

binde in der liste auch das SelectedItem zum viewmodel, und in der viewmodel setzt du das einfach auf null

<ListBox ItemsSource="{Binding Items}" IsSynchronizedWithCurrentItem="True" SelectedItem="{Binding ActiveItem}" ... />

//viewModel

private void Deselect()
{
    ActiveItem = null;
}
L
Lector Themenstarter:in
862 Beiträge seit 2006
vor 14 Jahren

Das wird so nicht gehen da ich nur ViewModels für die einzelnen Listenelemente habe.
Die ItemsSource-Eigenschaft besteht aus einer ObservableCollection aus diesen ViewModels. Und eine ObservableCollection weis nichts von irgendwelchen Selektierungen.

6.862 Beiträge seit 2003
vor 14 Jahren

Die ItemsSource-Eigenschaft besteht aus einer ObservableCollection aus diesen ViewModels. Und eine ObservableCollection weis nichts von irgendwelchen Selektierungen.

Jein 😃 Sie weiß natürlich direkt nichts von der Selektierung, aber für die ItemsSource wird implizit eine CollectionView erzeugt. Man hat nie direkt die Collection gebunden. Und diese CollectionView, weiß sehr wohl welches Item grad selektiert ist.

Baka wa shinanakya naoranai.

Mein XING Profil.

U
1.578 Beiträge seit 2009
vor 14 Jahren

daher erstellst du ja das binding

hier mal pseudo

public class BlaViewModel : ViewModelBase
{
    public ObservableCollection<ItemViewModel> Items { get; set; }
    public BlaViewModel()
    {
        Items = new ObservableCollection<ItemViewModel>();
        //fill Items
        ActiveItem = Items.FirstOrDefault();
    }

    public ItemViewModel ActiveItem
    {
        get { return _activeItem; }
        set
        {
            _activeItem = value;
            OnPropertyChanged("ActiveItem");
        }
    }
    private ItemViewModel _activeItem { get; set; }

    private void Deactivate()
    {
        ActiveItem = null;
    }
}

im xaml dann einfach wie schon beschrieben

<ListBox ItemsSource="{Binding Items}" IsSynchronizedWithCurrentItem="True" SelectedItem="{Binding ActiveItem}" ... />
L
Lector Themenstarter:in
862 Beiträge seit 2006
vor 14 Jahren

Erstmal danke für die Vorschläge.

Bei der Idee von Mr. Evil müsste ich jedoch auch für die Collection einen eigenen ViewModel-Wrapper machen. Was mir daran nicht gefällt ist die Tatsache dass dann das ViewModel durch das ActiveItem-Property wiederum von der View abhängig ist. Und es gibt in meiner Anwendung durchaus auch Views in denen Collections aus dem selben ViewModels nur als ItemsControl ohne Selektierung angezeigt werden. Das würde zwar trotzdem funktionieren ist aber meiner Meinung nach etwa genauso unschön wie meine Code-Behind-Zeile.

Eine perfekte Lösung mit der ich allein in XAML die Listbox-Selektierung aufheben kann scheint es anscheinend nicht zu geben?

Eher interressant fände ich den Ansatz über eine CollectionView da dies eine reine GUI-Klasse ist aber ich vermute dass ich über einen Button genauso wenig per XAML darauf zugreifen kann...

143 Beiträge seit 2008
vor 14 Jahren

Wo bekommst du denn die Itemsource her da musst du doch irgendwo eine Klasse haben, die die ObservableCollection enthält. Dort kannst du dieses Property doch anlegen. Und wie bekommst du denn momentan im Code heraus welches Item selectiert ist, ich mach das immer über so ein Property? 🤔

Gruß Timo

U
1.578 Beiträge seit 2009
vor 14 Jahren

Erstmal danke für die Vorschläge.

Bei der Idee von Mr. Evil müsste ich jedoch auch für die Collection einen eigenen ViewModel-Wrapper machen.

hae? wie omit schon sagte, eine klasse mit der ObservableCollection hast du doch schon, du brauchst da doch nur noch ein property mehr definieren und das wars?!

Was mir daran nicht gefällt ist die Tatsache dass dann das ViewModel durch das ActiveItem-Property wiederum von der View abhängig ist.

eh, ne, wieso?
das activeitem ist fuer eine view immer das ausgewaehlte item, aber auch immer das "aktive" item, kannst es also im code oder in der view verwenden
und es ist auch egal ob es eine listbox, listview, combobox oder itemscontrol ist - in der viewmodel immer gleich

Und es gibt in meiner Anwendung durchaus auch Views in denen Collections aus dem selben ViewModels nur als ItemsControl ohne Selektierung angezeigt werden. Das würde zwar trotzdem funktionieren ist aber meiner Meinung nach etwa genauso unschön wie meine Code-Behind-Zeile.

du kannst doch problemlos mehrere controls gleichzeitig auf die observablecollection zeigen lassen - wie schon geschrieben ist es der viewmodel voellig egal wer, und ob es irgendwo irgendwie angezeigt wird

Eine perfekte Lösung mit der ich allein in XAML die Listbox-Selektierung aufheben kann scheint es anscheinend nicht zu geben?

Eher interressant fände ich den Ansatz über eine CollectionView da dies eine reine GUI-Klasse ist aber ich vermute dass ich über einen Button genauso wenig per XAML darauf zugreifen kann... ich wuesste spontan nix

6.862 Beiträge seit 2003
vor 14 Jahren

Hallo,

Eher interressant fände ich den Ansatz über eine CollectionView da dies eine reine GUI-Klasse ist aber ich vermute dass ich über einen Button genauso wenig per XAML darauf zugreifen kann...

Wieso denken alle(ist mir in mehreren Threads jetzt aufgefallen) bei CollectionView an eine GUI? Das hat mit GUI rein gar nichts zu tun. Nur weil das Wort View drin vorkommt? In ViewModel kommt auch View drin vor aber es hat nichts mir der GUI zu tun.

Wenn du dein ViewModel hast, dann verwende statt eines Properties mit der ObservableCollection, eines mit der CollectionView als Typ. Und dann kannst du im ViewModel auch über die CollectionView das selektierte Item verändern.

In etwas so (kleines primitives Beispiel - nicht MVVM, soll aber auch nur Prinzip veranschaulichen):

 public class TestDataList {

        public TestDataList() {
            data.Add("Dies");
            data.Add("ist");
            data.Add("ein");
            data.Add("Test!");

            listData = CollectionViewSource.GetDefaultView(data);
        }

        private ICollectionView listData;
        private ObservableCollection<string> data = new ObservableCollection<string>();

        public ICollectionView ListData {
            get {
                return listData;
            }
        }
    }

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel>
        <ListView x:Name="liste" IsSynchronizedWithCurrentItem="True" />
        <StackPanel Orientation="Horizontal">
            <Button Content="Deselect all" x:Name="deselectButton" Click="deselectButton_Click" />
        </StackPanel>
    </StackPanel>
</Window>
    public partial class MainWindow : Window {

        TestDataList list = new TestDataList();

        public MainWindow() {
            InitializeComponent();
            liste.ItemsSource = list.ListData;
        }

        private void deselectButton_Click(object sender, RoutedEventArgs e) {
            list.ListData.MoveCurrentToPosition(-1);
        }
    }

EDIT: Seh grad das ich dich glaub ich falsch verstanden hab. Du willst es ja rein in GUI erledigen ohne Code oder? Da fällt mir spontan auch kein Weg ein, aber ich denke meine vorgestellte Lösung ist eigentlich ganz machbar, weil du in den Code Behind der XAMLs nichts mehr zu stehen hättest und statt dessen einfach normal mit nem Command das ViewModel veranlassen könntest zum deselektieren des Items.

Baka wa shinanakya naoranai.

Mein XING Profil.

U
1.578 Beiträge seit 2009
vor 14 Jahren

da muss ich dir recht geben
ich finde aber die direkte verwendung eines "ActiveItem" oder wie man es nennen mag logischer und auch sinnvoller
sieht man auch an c# code in den models - wenn man da eine List hat, dann verwendet man so etwas auch nicht

ich sah die CollectionView immer als wrapper um ein "Current" zur verfuegung zu stellen - nur das mach ich lieber direkt - ist eher so ne glaubens frage

6.862 Beiträge seit 2003
vor 14 Jahren

Hallo,

bei deiner Lösung oben hast du ja aber das Problem, das das ActiveItem nur synchron gehalten wird, weil du im XAML das Binding angegeben hast aus SelectedItem. Aber dein ViewModel an sich ist nicht ein der Lage das zu machen. Dabei sollte es ja grad das ViewModel tun um als eigenständiges ViewModel agieren zu können. Du benutzt momentan die View um eine Funktionalität fürs ViewModel herzustellen, die es alleine nicht kann.

Baka wa shinanakya naoranai.

Mein XING Profil.

U
1.578 Beiträge seit 2009
vor 14 Jahren

wenn eine view das "ActiveItem" braucht, dann muss sich die view auch darum kuemmern

das viewmodel ist als bindemittel ja nur dumm - es stellt nur bereit

wenn die view es benutzt ist gut, wenn nicht auch kein ding - die viewmodel verliert ja nichts wenn das property zur verfuegung gestellt wird

L
Lector Themenstarter:in
862 Beiträge seit 2006
vor 14 Jahren

Also erstmal zur ObservableCollection:

Es handelt sich hierbei eigendlich um eine von ReadOnlyObservableCollection abgeleitete Klasse welche Objekte aus dem Internet lädt. Diese wird in XAML direkt instanziiert und mit einigen Properties belegt.

Es existiert also kein ViewModel welches welches die ObservableCollection enthält. Man könnte aber die ObservableCollection als ViewModel ansehen weil es die geladenen Objekte als ViewModel zur verfügung stellt.

Jetzt könnte man natürlich sagen dass man ein Active-Item-Property in dieser Collection macht. Meiner Ansicht nach ist eine Selektierung jedoch GUI-Sache von irgendwelchen ListBoxen. Da diese ObsCol allerdings eher auf der ViewModel-Schicht angesiedelt ist möchte ich Selektierungslogiken dort vermeiden. Angenommen ich hätte 2 unterschiedliche Views welche diese Objekte auflisten wären dort die Selektierungen auch immer geich. Das kann man als Vorteil ansehen. Ich möchte solche Abhängigkeiten jedoch eher vermeiden.

Normalerweise hätte ich bei diesen Szenario eine Lösung per Attached-Behavior gemacht. Also einen ListBox-Unselect-Command und ein Attached-Property für die ListBox damit sie bei diesen Command die Selektierung aufhebt.
Das Problem ist jedoch dass ich per XAML vom Button aus nicht auf die ListBox zugreifen kann. Zumindest wüsste ich nicht wie.

Aber da eine reine XAML-Seitige Lösung wohl nicht geht wirds wohl vorerst beim Click-Handler bleiben da ich das Active-Item-Property wie oben beschrieben eher für ein künstliches Hilfsproperty halte welches in die View und nicht ins ViewModel gehört.

Trotzdem danke für die Vorschläge.

U
1.578 Beiträge seit 2009
vor 14 Jahren

najo nicht ganz
das ActiveItem bezeichnet ja ein "aktivierted" objekt aus der liste
das es am ende fuer eine selektion verwendet wird weiss die viewmodel klasse ja nicht
man koennte zb dann sagen "loesche das aktivierte item"
dann delegiert die viewmodel das aktive item auch an die models weiter
entsprechend ist es aus der view sich zwar nur fuer die selektion, aber nicht fuer die viewmodel

wogegen eine collectionview die items nur virtuell filtert, sortiert oder selektiert statt es richtig in der liste zu machen - daher ist die collectionview auch ein view objekt und das hat nichts in den viewmodels zu suchen...

6.862 Beiträge seit 2003
vor 14 Jahren

Hallo,

das viewmodel ist als bindemittel ja nur dumm - es stellt nur bereit

Tut es bei dir doch aber gar nicht! Du hast zwar im ViewModel ein Property welches das aktive Item halten kann, aber mit der Funktionalität hat dein ViewModel nichts zu tun. Entweder hat das ViewModel Funktionalität um das aktive Item zu verwalten, dann ist dort das Property richtig. Wenn es wie in deinem Fall aber durch die View verwaltet wird, dann hat das Property im ViewModel nichts zu suchen, sondern ist rein View intern interessant und sollte dann auch dort deklariert werden.

Die View funktioniert in dem Beispiel nur wenn das ViewModel nen Property für das aktive Item hat, und das ViewModel funktioniert nur wenn die View das aktive Item setzt. Sag jetzt nicht das das sauber getrennt ist nach dem MVVM Gedanken.

wogegen eine collectionview die items nur virtuell filtert, sortiert oder selektiert statt es richtig in der liste zu machen - daher ist die collectionview auch ein view objekt und das hat nichts in den viewmodels zu suchen...

Mit dem ersten Teil des Satzes geh großteils mit. Das filtern, sortieren und so ist sozusagen virtuell, da beim Filtern nichtpassende Objekte jetzt nicht gelöscht werden und so. Aber die Objekte in der View sind die der darunterliegenden Collection und Änderung an denen werden auch durchpropagiert.

Aber zweite Satzteil, das ne CollectionView nicht in ein ViewModel gehört ist totaler Mist. Ich weiß nicht woher der Reflex kommt beim Wort "View" sofort immer an die GUI zu denken. Eine CollectionView bietet einfach eine logische Sichtweise auf eine Collection. Und diese kann anders sein als die OriginalCollection, seis nun sortiert, gefilter, gruppiert. Aber eine CollectionView ist immer noch eine Collection! Diese hat absolut gar nichts mit einer View im MVVM Sinne zu tun. Es ist immer noch eine Aufzählung von Daten. Ich verstehe absolut nicht wie du zu der Aussage kommst das eine CollectionView nur in ein View (im Sinne von MVVM) Objekt gehört. Nur weil das Wort View im Namen vorkommt?

Baka wa shinanakya naoranai.

Mein XING Profil.

U
1.578 Beiträge seit 2009
vor 14 Jahren

ne
weil du das "view" falsch verstehst
"view" ist nicht nur das was der benutzer sieht
eine view ist eine sicht auf daten die nichts mit der bearbeitung zu tun hat
die collectionview ist eine view auf eine collection - also eine spezielle ansicht der daten
und das ist eine view - weiss gar nicht was man da missverstehen kann

und was das propertie an geht - die viewmodel ist das dumme bindeglied was einfach ein property anbietet - das dieses property zufaellig in der view das ausgewaehlte item ist weiss die viewmodel ja nicht
die viewmodel weiss nicht wofuer das propertie gut ist - es delegiert es immer nur weiter so wie ein command das moechte
mit funktionalitaet hat das auch nichts zu tun - die viewmodel hat nur den zweck properties zur verfuegung zu stellen die irgendwo irgendwie verwendet werden koennen - des weiteren wird fuer jede methode im model ein command zur verfuegung gestellt

in den beispiel so geb ich dir recht - das das activeitem nur zum deselektieren verwendet wird ist es sinn befreit
besser waere das per attached propertie
nur das ist ja nicht der standard fall
der standard fall ist der das das activeitem noch andere aufgaben hat
zb gezieltes loeschen (entf taste) oder editieren des aktivierten items

dh die view setzt in einem viewmodel ein properties, und sagt dan mittels command was damit passieren soll - zeige details - loesche - etc
die viewmodel hat es einfach nur und wartet auf commands - und dann wird das active item an den models weiter delegiert oder aehnliches, je nach anwendungsfall

L
Lector Themenstarter:in
862 Beiträge seit 2006
vor 14 Jahren

und was das propertie an geht - die viewmodel ist das dumme bindeglied was einfach ein property anbietet - das dieses property zufaellig in der view das ausgewaehlte item ist weiss die viewmodel ja nicht

Nun wenn das ViewModel nur ein Bindeglied ohne eigene Funktionalität ist darf es aber auch nicht eigenmächtig Properties anbieten.
Und für Anwendungsfälle wie Löschen, etc... wären dass doch Commands welche sich auf die einzelnen Objekte und nicht auf die Views beziehen. Das würde man dadurch realisieren indem mach im ItemTemplte einen Löschen-Button macht oder einen Button mit CommandBinding nach ListBox.SelectedItem.Delete. Grundsätzlich ware das Property dann doch nur fürs Unselekt zu gebrauchen.

Mal ausgehend davon dass ich für die ListBox ein Behavior machen würde mit dem ich sie per Command deselektieren würde, wäre es im oben genannten XAML-Code möglich vom Button aus einen Command an die ListBox zu senden?

Ich würde diesen Ansatz wesentlich sauberer finden da ich das Behavior wiederverwenden kann und ich immer noch nicht vom Sinn dieses ActiveItem-Properties überzeugt bin.

6.862 Beiträge seit 2003
vor 14 Jahren

Zu der View Problematik:

Ich hab meine Aussage konkret auf deinen Satz bezogen:

...daher ist die collectionview auch ein view objekt und das hat nichts in den viewmodels zu suchen...

Vielleicht verstehen wir uns auch nicht richtig weil das Wort View ja in verschiedenen Kontexten verwendet wird. Um das mal klar zu stellen: Wir reden von MVVM und dort haben wir die View (ich nenns der Einfachhalt halber mal pauschal "GUI") und das ViewModel( die "Daten" - und noch das Model hinter dem ViewModel, aber das kann ja hier in der Betrachtung vernachlässigt werden). Du sagst ja in deinem obigen Satz dass die CollectionView nicht ins ViewModel gehört, sondern weils ein "View" Objekt ist, in die View( sprich in die GUI). Hab ich das richtig verstanden?

die collectionview ist eine view auf eine collection - also eine spezielle ansicht der daten Genau das hab ich in meinem Beitrag ja auch geschrieben.
Eine CollectionView bietet einfach eine logische Sichtweise auf eine Collection. Und diese kann anders sein als die OriginalCollection, seis nun sortiert, gefilter, gruppiert Mit der Aussage geh ich voll mit.

Aber die CollectionView ist keine View im Sinne von MVVM wo die Views praktisch die GUI sind. Die CollectionView ist genau wie eine normale Collection, eine Liste von Daten, sieht man auch ganz gut wenn man mal guckt welche Interfaces CollectionView implementiert : IEnumerable, INotifyCollectionChanged, INotifyPropertyChanged und noch andere. Fällt da was auf? Klingen alle 3 doch sehr danach als wäre die CollectionView ne Menge von Daten oder? Und genau das ist sie auch. Man hätte die Klasse auch FilteredSortedGroupedCollection nennen können. Es ist eine ganz normale, datenhaltende Klasse, so wie die primitiven Datentypen oder jedes selber geschriebene Model oder ViewModel. Deshalb kann man die Klasse auch ganz normal in seinen Datenklassen verwenden und deshalb verstehe ich, wie schon im letzten Beitrag geschrieben, nicht deine obige Aussage, warum die CollectionView nichts im ViewModel zu tun hat.

Übrigens, für die CollectionView (die wie ich grad versucht hab rüberzubringen, ja eine Datenklasse ist) gibt es mit der CollectionViewSource das passende Pendant um sie in XAML verwenden zu können. In der MVVM View, da wo du sie hinstecken möchtest, verwendet man gerade nicht die CollectionView, sondern die CollectionViewSource.

Zu dem Property:
Mit deinen zusätzlichen Erklärungen verstehe ich wie du das ActiveItem einsetzen möchtest und sehe auch einen gewissen Sinn hinter deinen Erklärungen. Trotzdem fühlt sich das für mich irgendwie falsch an.

dh die view setzt in einem viewmodel ein properties, und sagt dan mittels command was damit passieren soll - zeige details - loesche - etc

Dafür gibts Command Parameter! Da übergibst du das was das Command brauch um ausgeführt zu werden. Soll ein Item gelöscht werden, übergibt man natürlich das zu löschende Item. Soll das ViewModel vielleicht eine Detailansicht zum editieren öffnen, übergibt man natürlich das Item welches editiert werden soll. Aber das in den Commands und nicht indem man hofft das ein ViewModel ein Property hat wo man Daten ablegen kann. Dein Ansatz ähnelt ein bisschen dem Vorgehen mit "globalen" Variablen das man ja öfter mal sieht. Statt ordentlich die benötigten Daten dort zu übergeben wo sie benötigt werden, packt man sie an eine Stelle von woaus sie von den verschiedenen Programmteilen wo man die braucht, erreichbar ist. Im Prinzip gibt bei deinem Vorgehen ja die View vor, wie das ViewModel auszusehen hat.

Nehmen wir mal an wir hätten so ne Klasse die als Property ne Collection hat die man bearbeiten möchte. Nach deinem Beispiel hätten wir noch zusätzlich ein Property welches das Datum hält welches verarbeitet werden soll. Nehmen wir wieder den Löschvorgang eines Items aus der Collection. Bei dir würde man das Datum welches gelöscht werden soll, dem einzelnen Property zuweisen und ne Löschen Methode ohne Parameter aufrufen welches dann dieses einzelne Item aus der Liste löscht. Das macht doch keinen Sinn und wird nirgends gemacht. Stattdessen übergibt man das zu löschende Datum der Lösch Methode.

EDIT: Zum Property was ergänzt.

Baka wa shinanakya naoranai.

Mein XING Profil.

U
1.578 Beiträge seit 2009
vor 14 Jahren

Mal ausgehend davon dass ich für die ListBox ein Behavior machen würde mit dem ich sie per Command deselektieren würde, wäre es im oben genannten XAML-Code möglich vom Button aus einen Command an die ListBox zu senden?

ich versteh nicht was du genau vor hast - du hast ein attached propertie fuer die listbox und willst das aufrufen von einem command eines items in der liste ?
kannst du mal deine idee mit code skizzieren ?

Zu der View Problematik:

Ich hab meine Aussage konkret auf deinen Satz bezogen:

...daher ist die collectionview auch ein view objekt und das hat nichts in den viewmodels zu suchen...

Vielleicht verstehen wir uns auch nicht richtig weil das Wort View ja in verschiedenen Kontexten verwendet wird. Um das mal klar zu stellen: Wir reden von MVVM und dort haben wir die View (ich nenns der Einfachhalt halber mal pauschal "GUI") und das ViewModel( die "Daten" - und noch das Model hinter dem ViewModel, aber das kann ja hier in der Betrachtung vernachlässigt werden). Du sagst ja in deinem obigen Satz dass die CollectionView nicht ins ViewModel gehört, sondern weils ein "View" Objekt ist, in die View( sprich in die GUI). Hab ich das richtig verstanden?

nein
view != gui
das muss man schon unterscheiden
ich zitiere mich mal selber

eine view ist eine sicht auf daten die nichts mit der bearbeitung zu tun hat

die collectionview ist eine ansicht der daten - kann auch ohne gui verwendet werden, bleibt aber eine view
view == "daten_ansicht_"

Aber die CollectionView ist keine View im Sinne von MVVM wo die Views praktisch die GUI sind.

genau das ist der kausus knacksus #gg view bzw view objekte sind nicht immer gui elemente - es ist nur meistens so

Die CollectionView ist genau wie eine normale Collection, eine Liste von Daten, sieht man auch ganz gut wenn man mal guckt welche Interfaces CollectionView implementiert : IEnumerable, INotifyCollectionChanged, INotifyPropertyChanged und noch andere. Fällt da was auf? Klingen alle 3 doch sehr danach als wäre die CollectionView ne Menge von Daten oder? Und genau das ist sie auch. Man hätte die Klasse auch FilteredSortedGroupedCollection nennen können. Es ist eine ganz normale, datenhaltende Klasse, so wie die primitiven Datentypen oder jedes selber geschriebene Model oder ViewModel. Deshalb kann man die Klasse auch ganz normal in seinen Datenklassen verwenden und deshalb verstehe ich, wie schon im letzten Beitrag geschrieben, nicht deine obige Aussage, warum die CollectionView nichts im ViewModel zu tun hat.

muss ich wiedersprechen - die collectionview ist keine normale collection - die collectionview ist nur die ansicht einer anderen collection darunter
ich zitiere mal den comment von microsoft zu dieser klasse:
"Initializes a new instance of the System.Windows.Data.CollectionView class that represents** a view of the specified collection**."
das bringt es ja ganz gut auf den punkt - es eine view auf eine bestehende collection - nicht mehr und nicht weniger

Übrigens, für die CollectionView (die wie ich grad versucht hab rüberzubringen, ja eine Datenklasse ist) gibt es mit der CollectionViewSource das passende Pendant um sie in XAML verwenden zu können. In der MVVM View, da wo du sie hinstecken möchtest, verwendet man gerade nicht die CollectionView, sondern die CollectionViewSource.

CollectionView, ICollectionView und welche es noch gibt sind einfach keine objekte fuer viewmodels - in den views ist das schon legitim


<CollectionViewSource x:Key="src" Source="{Binding Path=XYZ}">
    <CollectionViewSource.GroupDescriptions>
        <PropertyGroupDescription PropertyName="ABC" />
    </CollectionViewSource.GroupDescriptions>
    <CollectionViewSource.SortDescriptions>
        <scm:SortDescription PropertyName="DEF" Direction="Ascending" />
    </CollectionViewSource.SortDescriptions>
</CollectionViewSource>

in der view ist das erlaubt - da die sich selber natuerlich kennt

(nur um missverstaendnisse vor zu beugen - nur weils im .net framework ist heisst das nicht das man es auch im mvvm pattern verwenden kann)

mvvm rules punkt 3
die CollectionView ist ein visual element da es daten visualisiert (da die reelen daten nicht geaendert werden)

6.862 Beiträge seit 2003
vor 14 Jahren

Ich fang mal hinten an 😃


>
punkt 3

Ohne es in irgendeiner Art böse zu meinen, sind solche Zitate nutzlos. Ich kann mich auch selber zitieren mit Aussagen zu meiner Meinung, dadurch werden die Aussagen aber kein bisschen mehr belegt 😃
Dem halte ich spontan mal 5 zufällige Links entgegen die Google auf der ersten Suchseite zu CollectionView und MVVM gibt:
http://webenliven-space.de/dotnetblog/post/2009/01/23/MVVM-(Model-View-ViewModel)-mit-Expression-Blend-e28093-Teil-1.aspx
http://mark-dot-net.blogspot.com/2009/03/binding-combo-boxes-in-wpf-with-mvvm.html
http://stackoverflow.com/questions/979317/mvvm-collectionview-in-viewmodel-or-collectionviewsource-in-xaml
http://www.silverlightplayground.org/post/2009/07/18/Use-CollectionViewSource-effectively-in-MVVM-applications.aspx
http://www.biggle.de/blog/databinding-wpf-mvvm-pattern
Guck mal wo dort die CollectionView benutzt wird. Immer im ViewModel 😃

die CollectionView ist ein visual element da es daten visualisiert (da die reelen daten nicht geaendert werden)

Hmm, Visual, ein interessanter Stichpunkt. Kannst du mir zeigen wo in der WPF Klassenhierachie von DispatcherObject über Visual und UIElement usw. die CollectionView steht? Und wie sieht sie aus, wenn es ein Visual in irgend einer Art ist, sollte es doch eine Darstellung haben? Oder ist es nicht eher so das die CollectionView ja selber durch andere UI Elemente wie z.B. ListView visualisiert wird? Heißt das nicht im Umkehrschluss das die CollectionView ein Datum ist wenn sie durch andere UIElemente dargestellt wird?

nein
view != gui

Das habe ich nicht geschrieben. Ich habe geschrieben das die View in MVVM die GUI repräsentiert. Die Views in MVVM visualisieren die ViewModels.

Das die View im Sinne einer logisch anderen Sicht auf Daten wie sie bei der CollectionView verwendet wird, nichts mit GUI zu tun hat, ist mir klar und das sag ich auch schon die ganze Diskussion.

ich zitiere mich mal selber

Wie schon oben gesagt, eigene Zitate bringen nichts. Ich guck mir gerne andere Links an, die deinen Standpunkt untermauern. Nur eigene Zitate bringen ja keine neuen Argumente in die Diskussion. Ich lese oft irgendwelche Artikel und Blogeinträge zu WPF Themen und auch viele zu MVVM. In noch keinem einzigen hab ich jemals gesehen das dein Standpunkt vertreten wird. Wenn du da einen Link hast, schau ich ihn mir gerne an.

CollectionView, ICollectionView und welche es noch gibt sind einfach keine objekte fuer viewmodels - in den views ist das schon legitim Wie begründest du das? Und was sagst du dann zu dem SourceCollection Property der CollectionView? Die Daten werden direkt bis in die View propagiert? Sehr MVVM like 😃 Dachte immer die View in MVVM sollte die Daten nicht kennen.

Du kannst auch gerne noch was zu der Property Problematik schreiben wenn du möchtest. hatte da was noch im anderen Beitrag ergänzt.

Baka wa shinanakya naoranai.

Mein XING Profil.

U
1.578 Beiträge seit 2009
vor 14 Jahren

Zu dem Property:
Mit deinen zusätzlichen Erklärungen verstehe ich wie du das ActiveItem einsetzen möchtest und sehe auch einen gewissen Sinn hinter deinen Erklärungen. Trotzdem fühlt sich das für mich irgendwie falsch an.

dh die view setzt in einem viewmodel ein properties, und sagt dan mittels command was damit passieren soll - zeige details - loesche - etc
Dafür gibts Command Parameter! Da übergibst du das was das Command brauch um ausgeführt zu werden. Soll ein Item gelöscht werden, übergibt man natürlich das zu löschende Item. Soll das ViewModel vielleicht eine Detailansicht zum editieren öffnen, übergibt man natürlich das Item welches editiert werden soll. Aber das in den Commands und nicht indem man hofft das ein ViewModel ein Property hat wo man Daten ablegen kann. Dein Ansatz ähnelt ein bisschen dem Vorgehen mit "globalen" Variablen das man ja öfter mal sieht. Statt ordentlich die benötigten Daten dort zu übergeben wo sie benötigt werden, packt man sie an eine Stelle von woaus sie von den verschiedenen Programmteilen wo man die braucht, erreichbar ist. Im Prinzip gibt bei deinem Vorgehen ja die View vor, wie das ViewModel auszusehen hat.

das problem ist ja das das commandparameter oft schon von anderen informationen belegt wird
zb soll das item geloescht werden wenn das KeyUp event auf kommt - dann muss man noch pruefen welche taste das war
das loest man dann zwar in einem converter (da die viewmodel nicht die tastatureingaben ueberprueft) aber das aendert nichts das mann entweder das objekt, oder den entsprechenden parameter hat

die viewmodel bestimmt uerhaupt nichts
die viewmodel bietet nur an - obs benutzt wird ist doch voellig irrelevant

Nehmen wir mal an wir hätten so ne Klasse die als Property ne Collection hat die man bearbeiten möchte. Nach deinem Beispiel hätten wir noch zusätzlich ein Property welches das Datum hält welches verarbeitet werden soll. Nehmen wir wieder den Löschvorgang eines Items aus der Collection. Bei dir würde man das Datum welches gelöscht werden soll, dem einzelnen Property zuweisen und ne Löschen Methode ohne Parameter aufrufen welches dann dieses einzelne Item aus der Liste löscht. Das macht doch keinen Sinn und wird nirgends gemacht. Stattdessen übergibt man das zu löschende Datum der Lösch Methode.

wie oben schon geschrieben - da das command von einem event kommt, und man den parameter nicht belegen darf, da das keydownevent an den converter gegeben wird ist es nicht benutzbar

Ohne es in irgendeiner Art böse zu meinen, sind solche Zitate nutzlos. Ich kann mich auch selber zitieren mit Aussagen zu meiner Meinung, dadurch werden die Aussagen aber kein bisschen mehr belegt 😃

eine belegung war nicht mein ziel, ich wollte nur zeigen wie ich es damals schon formulierte {o;

Dem halte ich spontan mal 5 zufällige Links entgegen die Google auf der ersten Suchseite zu CollectionView und MVVM gibt:

wenn man so will findet man auch viele links die code in die code behind packen und sagen es waere mvvm

Hmm, Visual, ein interessanter Stichpunkt. Kannst du mir zeigen wo in der WPF Klassenhierachie von DispatcherObject über Visual und UIElement usw. die CollectionView steht? Und wie sieht sie aus, wenn es ein Visual in irgend einer Art ist, sollte es doch eine Darstellung haben? Oder ist es nicht eher so das die CollectionView ja selber durch andere UI Elemente wie z.B. ListView visualisiert wird? Heißt das nicht im Umkehrschluss das die CollectionView ein Datum ist wenn sie durch andere UIElemente dargestellt wird?

da ist genau das problem, wenn du an view denkst, denkst du immer das es entweder direkt ein gui objekt ist oder von visuell abgeleitet
ich sagte doch immer wieder: die view ist eine ansicht der daten die nichts mit der bearbeitung zu tun hat
da ist es voellig egal ob es dem user gezeigt wird (gui) oder von visual oder uielement ableitet
wenn ich visual sagte meinte ich auch nur visuell, wenn dir die deutsche uebersetzung lieber ist, nicht das objekt

Das habe ich nicht geschrieben. Ich habe geschrieben das die View in MVVM die GUI repräsentiert.

kein wunder das du so argumentierst wenn du das denkst, die view repraesentiert eben nicht nur die gui

Die Views in MVVM visualisieren die ViewModels.

WAS ? das glaubst du ernsthaft ? die viewmodels sind auch nur "dienstleister der models" - das bindeglied
sie stellen commands und properties bereit die irgend eine view konsumieren kann - die views visualisieren die daten, und die muessen einfach von den viewmodels anzeigbar gemacht werden
ich vergleiche das einfach mal mit meiner arbeit

(lokalisierung)
wir haben texte die muessen uebersetzt werden (quelltext) = models
ich bearbeite die so das sie uebermittelt und uebersetzt werden koennen = viewmodel
und die lsps uebersetzen das ganze zeug = views
und da repraesentieren die views nicht die viewmodels die daten
(die lsps repraesentieren nicht mich, ich bin nur das bindeglied (wobei den lsps egal ist wer ich bin solange es irgendjemand ist), sondern die repraesentieren den text

Das die View im Sinne einer logisch anderen Sicht auf Daten wie sie bei der CollectionView verwendet wird, nichts mit GUI zu tun hat, ist mir klar und das sag ich auch schon die ganze Diskussion.

gut, also sagst du selber das die collectionview eine view ist, und eine view gehoert nicht in die viewmodel {o;

Wie schon oben gesagt, eigene Zitate bringen nichts. Ich guck mir gerne andere Links an, die deinen Standpunkt untermauern. Nur eigene Zitate bringen ja keine neuen Argumente in die Diskussion. Ich lese oft irgendwelche Artikel und Blogeinträge zu WPF Themen und auch viele zu MVVM. In noch keinem einzigen hab ich jemals gesehen das dein Standpunkt vertreten wird. Wenn du da einen Link hast, schau ich ihn mir gerne an.

wie gesagt, ich zitiere mich nur selber um etwas was ich schonmal schrieb nochmal auf zu zeigen
du wirst bestimmt oft gelesen haben das die view und die viewmodels getrennt sind
mitlerweile hast du ja auch schon eingesehen das die collectionview eine view ist - folglich gehoerts nicht in die viewmodel
nur weil es andere lockerer sehen ist das kein argument, ich betrachte das mvvm pattern an sich sehr streng (und bin bisher sehr gut gefahren und hatte nie irgendwelche konflikte oder probleme dadurch)

CollectionView, ICollectionView und welche es noch gibt sind einfach keine objekte fuer viewmodels - in den views ist das schon legitim
Wie begründest du das?

wie schon die ganze zeit - die "CollectionView" sind view objekte

Und was sagst du dann zu dem SourceCollection Property der CollectionView?

hm ? was sagst du zu dem propertie einer listbox?! versteh nicht worauf du hinaus willst

Die Daten werden direkt bis in die View propagiert? Sehr MVVM like 😃 Dachte immer die View in MVVM sollte die Daten nicht kennen.

ehm - nein - wie kommst du darauf ?
die views visualisieren nur die obervablecollections, hat mit den CollectionView ja nichts zu tun
wenn die view es selber verwenden moechte - schoen - kann sie auch (hatte ich mit quelltext gezeigt)

ich zitiere ma deine links:
webliven-space: "Es stellt eine Ansicht zum Gruppieren, Sortieren, Filtern und Navigieren in einer Datenauflistung dar."
mark-dot-net: "I’m not sure yet whether using CollectionView is a better approach than the alternatives I have seen which bind the SelectedValue or SelectedItem property."
stackoverflow: "That should definitely be in the VM so that it can be tested" (komische logik, nur weils dann anders getestet werden kann solls in die viewmodel gehoeren ?)
silverlightplayground: finde nichts was es wert ist zu quoten, der benutzt so wie ich das les nur das propertie weil es code sparen will "However, if it were possible, the CollectionViewSource would force us to put a lot of code in the codebehind to handle the Filter event and the sorting property."
seine einzigste moeglichkeit die collectionview eg zu lassen ist code in der code behind ? ich sag nur: omg
biggle: nutzloser link, der zeigt nur code ohne begruendung

msdn: "Represents a view for grouping, sorting, filtering, and navigating a data collection."

deine links haben meine meinung eher untermauert als wiederlegt
(microsoft selber verwendet es auch nur in der xaml, also in der view, ebenfalls eine bestaetigung: http://msdn.microsoft.com/en-us/magazine/dd419663.aspx) (wobei ich auch da nicht in allen punkten ueberein stimme, hat jetzt aber nichts mit diesen collectionview teilen zu tun)

btw - sollten wir den thread evtl abtrennen ?

//dazuedit:
um es nochmal klar zu machen
die msdn selber sagt "Represents a view for grouping, sorting, filtering, and navigating a data collection."
und eine view hat nichts in der viewmodel zu suchen
versteh immernoch nicht was daran so unklar ist

L
Lector Themenstarter:in
862 Beiträge seit 2006
vor 14 Jahren

...Um mal wieder zurück zum Thema zu kommen:

Mal ausgehend davon dass ich für die ListBox ein Behavior machen würde mit dem ich sie per Command deselektieren würde, wäre es im oben genannten XAML-Code möglich vom Button aus einen Command an die ListBox zu senden?
ich versteh nicht was du genau vor hast - du hast ein attached propertie fuer die listbox und willst das aufrufen von einem command eines items in der liste ?
kannst du mal deine idee mit code skizzieren ?

Ich hab jetzt mal etwas rumprogrammiert und getestet und heraus kam ein Behavior mit dem ich ListBoxen rein per XAML deselektieren kann. Das Behavior sieht so aus:


/// <summary>
  /// Verschiedene ListBox-Verhalten
  /// </summary>
  public static class ListBoxBehavior
  {
    /// <summary>
    /// Command um die Selektierung einer ListBox aufzuheben
    /// </summary>
    public static readonly RoutedCommand UnselectCommand = new RoutedCommand("Unselect", typeof(ListBox));

    /// <summary>
    /// Ruft das UnselectOnCommand-Flag ab
    /// </summary>
    /// <param name="obj">Bezugsobjekt</param>
    /// <returns></returns>
    public static bool GetUnselectOnCommand(ListBox obj)
    {
      return (bool)obj.GetValue(UnselectOnCommandProperty);
    }
    /// <summary>
    /// Setzt das UnselectOnCommand-Flag
    /// </summary>
    /// <param name="obj">Bezugsobjekt</param>
    /// <param name="value">Neuer Wert</param>
    public static void SetUnselectOnCommand(ListBox obj, bool value)
    {
      obj.SetValue(UnselectOnCommandProperty, value);
    }
    /// <summary>
    /// Gibt an ob eine ListBox auf den UnselectCommand reagieren und die Selektierung aufheben soll
    /// </summary>
    public static readonly DependencyProperty UnselectOnCommandProperty =
        DependencyProperty.RegisterAttached("UnselectOnCommand", typeof(bool), typeof(ListBoxBehavior),
        new UIPropertyMetadata(false, onUnselectOnCommandChanged));

    private static void onUnselectOnCommandChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
      ListBox listBox = (ListBox)sender;
      if ((bool)e.NewValue)
      {
        UnselectCommandBinding binding = new UnselectCommandBinding(listBox);
        SetUnselectCommandBinding(listBox, binding);
        listBox.CommandBindings.Add(binding);
      }
      else
      {
        UnselectCommandBinding binding = GetUnselectCommandBinding(listBox);
        if (binding != null && listBox.CommandBindings.Contains(binding))
        {
          listBox.CommandBindings.Remove(binding);
          SetUnselectCommandBinding(listBox, null);
        }
      }
    }

    private static UnselectCommandBinding GetUnselectCommandBinding(ListBox obj)
    {
      return (UnselectCommandBinding)obj.GetValue(UnselectCommandBindingProperty);
    }
    private static void SetUnselectCommandBinding(ListBox obj, UnselectCommandBinding value)
    {
      obj.SetValue(UnselectCommandBindingProperty, value);
    }
    private static readonly DependencyProperty UnselectCommandBindingProperty =
        DependencyProperty.RegisterAttached("UnselectCommandBinding", typeof(UnselectCommandBinding), typeof(ListBoxBehavior),
        new UIPropertyMetadata(null));

    private class UnselectCommandBinding : CommandBinding
    {
      public UnselectCommandBinding(ListBox listBox)
        : base(UnselectCommand,
        (param, e) => { listBox.SelectedIndex = -1; },
        (param, e) => { e.CanExecute = true; })
      {
      }
    }
  }

Verwendet werden kann das ganze z.B. so:


<Button Content="Unselect" VerticalAlignment="Top" HorizontalAlignment="Center"
                Command="{x:Static Controls:ListBoxBehavior.UnselectCommand}" CommandTarget="{Binding ElementName=list}"/>
        <ListBox Grid.Row="1" Name="list" Controls:ListBoxBehavior.UnselectOnCommand="True">
            <ListBoxItem>Eins</ListBoxItem>
            <ListBoxItem>Zwei</ListBoxItem>
            <ListBoxItem>Drei</ListBoxItem>
        </ListBox>

Dieser Beispielcode funktioniert bereits. Ich habe das gerade getestet.
Da man auch von einem Template aus auf Elemente ausserhalb des Templates zugreifen kann funktioniert der Code auch in meinem ursprünglich genannten Code-Schnipsel. Jetzt kann ich mit einem Button eine ListBox-Selektierung aufheben OHNE Code-Behind und OHNE künstliche ViewModel-Properties. Alles rein GUI-Seitig (ich vermeide jetzt bewusst das Wort View 😉)

U
1.578 Beiträge seit 2009
vor 14 Jahren

deine loesung gefaellt mir wirklich gut {= - so hatte ich mir das auch schon fast gedacht

6.862 Beiträge seit 2003
vor 14 Jahren

...
das problem ist ja das das commandparameter oft schon von anderen informationen belegt wird...

Mag sehr gut sein das man noch mehr Informationen übergeben muss, aber man kann auch mehr als ein Objekt übergeben als Parameter...

Ist dir eigentlich aufgefallen das du meine Frage, warum du sagst dass CollectionViews nicht in ViewModels gehören, immer noch nicht belegt hast mit irgendwelchen Links die deinen Standpunkt vertreten?

Zu meinen geposteten Links:
Du zitierst aber ziemlich selektiv und lenkst damit ab 😃 Es geht ja gar nicht um das Thema welches dort drin behandelt wird, sondern einfach darum wo die CollectionView benutzt wurde. Und da kann ich aus jedem Link sinngemäß zitieren:

...
xyzViewModel {
...
   CollectionView ABC ...
}

Ich biete dir mal vielleicht noch nen Link
http://marlongrech.wordpress.com/2008/11/22/icollectionview-explained/
Von nem MVP in WPF und zitier mal auch fein:

ICollectionView is really a great tool especially when you are trying to separate the UI code from the business logic by using patterns such as M-V-VM. In the Demo application I compiled for this post you can see how to implement a nice ViewModel and use the ICollectionView to do all sort of stuff for the UI without having any problems because you do not have a reference to the UI objects

Genau der Standpunkt den ich die ganze Zeit schon vertrete.

In dein weiteren Erklärungen von wegen View = GUI drehst du mir ziemlich oft das Wort im Mund um und beachtest gar nicht das was ich hab versucht zu erklären.

Das Konzept View als eine bestimmte Ansicht auf Daten habe ich ja nie verneint. Diese Views müssen natürlich keine visuelle Darstellung haben. Aber das Wort View, in der Abkürzung MVVM, ist konzeptionell etwas anderes. Das habe ich die ganze Zeit versucht klar zu stellen. MVVM beschreibt doch einfach nur die Aufteilung der Anwendung in Daten/Funktionalität(M_VM) und Aussehen(V). Natürlich bietet die View in MVVM auch eine "Sicht" auf Model und ViewModel, aber die Sicht, wie die Daten konkret dargestellt werden sollen. Bei dem View im Wort MVVM geht es um die graphische Darstellung der Applikation.

Hier mal nen Artikel zu MVVM aus dem MSDN Magazine
http://msdn.microsoft.com/en-us/magazine/dd419663.aspx
und nen Zitat:

A view, then, becomes merely a rendering of a Presentation Model Warum da PresentationMode statt ViewModel steht, kann im Artikel nachgelesen werden. Ist jedenfalls das gleiche.

Du versuchst das Wort View in MVVM zu etwas zu generalisieren was es nicht ist. Es ist im MVVM Kontext die graphische Darstellung. Nichts weiter.

Eine "Datenansichtsview" hat mit dem Konzept View in MVVM nichts zu tun.

gut, also sagst du selber das die collectionview eine view ist, und eine view gehoert nicht in die viewmodel {o; Zum ersten Teil ja, sag ich die ganze Zeit, zum zweiten Teil nein. Da denkst du dir was aus was ich gar nicht gesagt habe. Warum eine CollectionView auch ins ViewModel passt hab ich ja versucht darzulegen.

du wirst bestimmt oft gelesen haben das die view und die viewmodels getrennt sind
mitlerweile hast du ja auch schon eingesehen das die collectionview eine view ist - folglich gehoerts nicht in die viewmodel

Eins muss man dir lassen. Du schreibst ziemlich geschickt und manipulierend. Du legst deine Meinung in meine Worte und man könnte glatt glaube das ich das so gemeint hab wie du geschrieben hast. Hab ich aber nicht! Du schnappst dir aus dem Kontext gerissen ne Aussage von mir von wegen CollectionView ist eine View (das es dabei nicht um die View im MVVM Sinne geht, ignorierst du in der Aussage völlig), all die anderen Stellen in meinen Erklärungen die deine Sichtweise widerlegen könnten, lässt du einfach weg.

nur weil es andere lockerer sehen ist das kein argument, ich betrachte das mvvm pattern an sich sehr streng (und bin bisher sehr gut gefahren und hatte nie irgendwelche konflikte oder probleme dadurch)

MVVM lässt Prinzipbedingt viel Spielraum für eigene Auslegungen, da stimm ich mit ein. Aber du versuchst deine Auslegung als die einzig wahre darzustellen und belegst es immer wieder nur mit deinen eigenen Aussagen. Zeig mir Material wo andere es so auslegen wie du. Bisher ist mir noch nichts in die Richtung untergekommen. Natürlich heißt das nicht das meine Sichtweise die absolut richtige ist, aber ich hab versucht Material zu verlinken welches meinen Standpunkt untermauert. Das fehlt mir in deiner Argumentation völlig und deshalb sehe ich nicht wieso dein Standpunkt richtig sein soll.

microsoft selber verwendet es auch nur in der xaml, also in der view, ebenfalls eine bestaetigung:
>
) (wobei ich auch da nicht in allen punkten ueberein stimme, hat jetzt aber nichts mit diesen collectionview teilen zu tun) Da wirfst du Klassen durcheinander wies dir passt. Im XAML wird immer nur die CollectionViewSource verwendet, nicht die CollectionView! Die CollectionViewSource ist noch nicht mal ne View und wurde nur geschaffen um Views in XAML nutzen zu können. Und die CollectionViews über die collectionViewSources in den MVVM Views nutzen zu können widerspricht sich nicht mit meinen Aussagen. Es geht mir immer noch um deine Behauptung das man CollectionViews nicht in ViewModels einsetzen darf.

die msdn selber sagt "Represents a view for grouping, sorting, filtering, and navigating a data collection."
und eine view hat nichts in der viewmodel zu suchen

Immer wieder das gleiche selektive zitieren um Aussagen ja ausm Kontext zu reißen. Bitte zeig mir die Stelle wo in der Dokumentation über MVVM Views gesprochen wird! Die Views aus deinem Zitat sind nicht die Views aus MVVM.

Baka wa shinanakya naoranai.

Mein XING Profil.

U
1.578 Beiträge seit 2009
vor 14 Jahren

...
das problem ist ja das das commandparameter oft schon von anderen informationen belegt wird...
Mag sehr gut sein das man noch mehr Informationen übergeben muss, aber man kann auch mehr als ein Objekt übergeben als Parameter...

zeig ma die du den command "delete active objekt" das entsprechende objekt mit gibst wenn es bei einem keydown passieren soll - also wenn der benutzer ENTF drueckt

bei mir waere es:
Dreckig:

<ListBox Events:EventBinding.EventCommandName="KeyDown KeyDownCommand" />
public class BlaViewModel : ViewModelBase
{
    public ObservableCollection<ItemViewModel> Items { get; set; }
    public ItemViewModel ActiveItem { get; set; } // mit propertychanged
    private void Delete(object param)
    {
        KeyEventArgs e = param as KeyEventArgs; // bin grad nicht sicher wegen den namen
        if (e.Key == Keys.Delete && ActiveItem != null)
            Items.Remove(ActiveItem); // inform models ?
    }

    public ICommand KeyDownCommand
    {
        get
        {
            if (_keyDownCommand == null)
                _keyDownCommand = new DelegateCommand(p => KeyDown(p));
            return _keyDownCommand;
        }
    }
    private ICommand _keyDownCommand { get; set; }
}

Sauberer:

<ListBox Events:EventBinding.EventCommandName="KeyDown DeleteCommand" Events:EventBinding.Converter="{StaticResource DeleteKeyConverter}" />
public sealed DeleteKeyConverter : IValueConverter
{
    // value = event type
    // property = event parameter zum pruefen
    public Convert(object value, Type targetType, object property, ...)
    {
        KeyEventArgs e = property as KeyEventArgs;
        if (e.Key == Keys.Delete)
            return true;
        return false;
    }
}
public class BlaViewModel : ViewModelBase
{
    public ObservableCollection<ItemViewModel> Items { get; set; }
    public ItemViewModel ActiveItem { get; set; } // mit propertychanged
    private void Delete(object param)
    {
        if ((bool)param && ActiveItem != null) // mal einfach gecastet
            Items.Remove(ActiveItem);
    }

    public ICommand DeleteCommand
    {
        get
        {
            if (_deleteCommand== null)
                _deleteCommand= new DelegateCommand(p => Delete(p));
            return _deleteCommand;
        }
    }
    private ICommand _deleteCommand { get; set; }
}

ich muss zugeben das die "saubere" variante gerade ausgedacht ist (und auch nicht wirklich sauber), ich mach es meistens auf den dreckigen weg - gefaellt mir aber auch ueberhaupt nicht - habe noch keine wirklich saubere loesung

wie wuerdest du das machen ? (mit dem uebergeben des objektes wie du es sagst)

Ist dir eigentlich aufgefallen das du meine Frage, warum du sagst dass CollectionViews nicht in ViewModels gehören, immer noch nicht belegt hast mit irgendwelchen Links die deinen Standpunkt vertreten?

warum schreist du immer nach links ? wird etwas legitimer nur weil mehrere es verwenden ?
(wenn mehrere leute klauen wird es doch auch nicht legaler - nur weis viele machen -.-)

ich habe in der ganzen diskusion hier nichtmal versucht welche zu finden, ich hab maximal deine links angeklickt die meine aussagen keineswegs wiederlegt haben

Zu meinen geposteten Links:
Du zitierst aber ziemlich selektiv und lenkst damit ab 😃 Es geht ja gar nicht um das Thema welches dort drin behandelt wird, sondern einfach darum wo die CollectionView benutzt wurde. Und da kann ich aus jedem Link sinngemäß zitieren:

...  
xyzViewModel {  
...  
   CollectionView ABC ...  
}  

den ganzen blog zitieren macht ja auch kein sinn - und ich zeigte stellen auf die anscheinend in deren betrachtung des ganzen missachtet wurde - und zwar das dieses objekt ein view objekt ist - haben alle geschrieben - aber alle auch missachtet

Ich biete dir mal vielleicht noch nen Link

>

Von nem MVP in WPF und zitier mal auch fein:

ICollectionView is really a great tool especially when you are trying to separate the UI code from the business logic by using patterns such as M-V-VM. In the Demo application I compiled for this post you can see how to implement a nice ViewModel and use the ICollectionView to do all sort of stuff for the UI without having any problems because you do not have a reference to the UI objects

Genau der Standpunkt den ich die ganze Zeit schon vertrete.

die collectionview hat zwar keine referenz auf ein ui objekt - aber wie ich doch die ganze zeit selber schon sagte - view != gui

In dein weiteren Erklärungen von wegen View = GUI drehst du mir ziemlich oft das Wort im Mund um und beachtest gar nicht das was ich hab versucht zu erklären.

Das Konzept View als eine bestimmte Ansicht auf Daten habe ich ja nie verneint. Diese Views müssen natürlich keine visuelle Darstellung haben. Aber das Wort View, in der Abkürzung MVVM, ist konzeptionell etwas anderes. Das habe ich die ganze Zeit versucht klar zu stellen. MVVM beschreibt doch einfach nur die Aufteilung der Anwendung in Daten/Funktionalität(M_VM) und Aussehen(V). Natürlich bietet die View in MVVM auch eine "Sicht" auf Model und ViewModel, aber die Sicht, wie die Daten konkret dargestellt werden sollen. Bei dem View im Wort MVVM geht es um die graphische Darstellung der Applikation.

und genau da kommen wir ja nicht auf einen gemeinsamen nenner - sodass wir uns immer im kreis drehen - die view ist eben nicht nur die grafische darsellung

Hier mal nen Artikel zu MVVM aus dem MSDN Magazine

>

und nen Zitat:

A view, then, becomes merely a rendering of a Presentation Model
Warum da PresentationMode statt ViewModel steht, kann im Artikel nachgelesen werden. Ist jedenfalls das gleiche.

ist ja nichts verkehrtes - die view kann natuerlich auch die viewmodel praesentieren (muss aber nicht), das hat mit der problematik (view objekt in der viewmodel) nichts zu tun

Du versuchst das Wort View in MVVM zu etwas zu generalisieren was es nicht ist. Es ist im MVVM Kontext die graphische Darstellung. Nichts weiter.

Eine "Datenansichtsview" hat mit dem Konzept View in MVVM nichts zu tun.

ich seh es halt sehr streng - fuer mich ist view eine ansicht - sei es gui oder daten ansicht
hab ich nie was anderes behauptet

gut, also sagst du selber das die collectionview eine view ist, und eine view gehoert nicht in die viewmodel {o;
Zum ersten Teil ja, sag ich die ganze Zeit, zum zweiten Teil nein. Da denkst du dir was aus was ich gar nicht gesagt habe. Warum eine CollectionView auch ins ViewModel passt hab ich ja versucht darzulegen.

du meinst das es in die viewmodel gehen kann da es kein gui element ist - das deckt sich auch mit deiner ansicht das view == gui ist
fuer mich ist es eben nicht so

du wirst bestimmt oft gelesen haben das die view und die viewmodels getrennt sind
mitlerweile hast du ja auch schon eingesehen das die collectionview eine view ist - folglich gehoerts nicht in die viewmodel
Eins muss man dir lassen. Du schreibst ziemlich geschickt und manipulierend. Du legst deine Meinung in meine Worte und man könnte glatt glaube das ich das so gemeint hab wie du geschrieben hast. Hab ich aber nicht! Du schnappst dir aus dem Kontext gerissen ne Aussage von mir von wegen CollectionView ist eine View (das es dabei nicht um die View im MVVM Sinne geht, ignorierst du in der Aussage völlig), all die anderen Stellen in meinen Erklärungen die deine Sichtweise widerlegen könnten, lässt du einfach weg.

in deiner interpretation des mvvm - nicht in meiner {o;
zudem lass ich nichts weg - ich zitiere wenn immer alles!

nur weil es andere lockerer sehen ist das kein argument, ich betrachte das mvvm pattern an sich sehr streng (und bin bisher sehr gut gefahren und hatte nie irgendwelche konflikte oder probleme dadurch)
MVVM lässt Prinzipbedingt viel Spielraum für eigene Auslegungen, da stimm ich mit ein. Aber du versuchst deine Auslegung als die einzig wahre darzustellen und belegst es immer wieder nur mit deinen eigenen Aussagen. Zeig mir Material wo andere es so auslegen wie du. Bisher ist mir noch nichts in die Richtung untergekommen. Natürlich heißt das nicht das meine Sichtweise die absolut richtige ist, aber ich hab versucht Material zu verlinken welches meinen Standpunkt untermauert. Das fehlt mir in deiner Argumentation völlig und deshalb sehe ich nicht wieso dein Standpunkt richtig sein soll.

ich habe nie gesagt das meine sicht die einzigst richtige ist - ich begruende nur warum ich so denke - ich schrieb auch schon im blog:
"All solutions shown in this blog, are not the “one and only”, also not the best, and I can bet that many other developers has another estimation ...
It should be noticed that my point of view to the pattern is very hard, many things I don’t allow, no exceptions like the “Code in Code Behind” and so on..."

microsoft selber verwendet es auch nur in der xaml, also in der view, ebenfalls eine bestaetigung:
>>
) (wobei ich auch da nicht in allen punkten ueberein stimme, hat jetzt aber nichts mit diesen collectionview teilen zu tun)
Da wirfst du Klassen durcheinander wies dir passt. Im XAML wird immer nur die CollectionViewSource verwendet, nicht die CollectionView! Die CollectionViewSource ist noch nicht mal ne View und wurde nur geschaffen um Views in XAML nutzen zu können. Und die CollectionViews über die collectionViewSources in den MVVM Views nutzen zu können widerspricht sich nicht mit meinen Aussagen. Es geht mir immer noch um deine Behauptung das man CollectionViews nicht in ViewModels einsetzen darf.

gut, die collectionviewsource ist nicht das selbe objekt, das ist mir klar, das aendert aber nichts das dort im beispiel eben kein view objekt (was die CollectionView ist) im viewmodel verwendet wird

die msdn selber sagt "Represents a view for grouping, sorting, filtering, and navigating a data collection."
und eine view hat nichts in der viewmodel zu suchen
Immer wieder das gleiche selektive zitieren um Aussagen ja ausm Kontext zu reißen. Bitte zeig mir die Stelle wo in der Dokumentation über MVVM Views gesprochen wird! Die Views aus deinem Zitat sind nicht die Views aus MVVM.

der zitat ist der comment aus der CollectionView - entsprechend passt es doch ?!

am ende ist es doch so - zusammengefasst:
du: view == gui
ich: view == view auf daten
entsprechend kommen wir nicht auf ein gemeinsamen nenner

(ich zitiere mich oft selber da ich mich eh staendig wiederhol - da du den standpunkt irgendwie nicht verstehen willst

6.862 Beiträge seit 2003
vor 14 Jahren

wie wuerdest du das machen ?

Das würd ich einfach so machen:

  <ListBox x:Name="myList" >
    <ListBox.InputBindings>
      <KeyBinding Key="Delete" Command="KeyDownCommand" CommandParameter="{Binding ElementName=myList, Path=SelectedItem}" />
    </ListBox.InputBindings>
  </ListBox>

warum schreist du immer nach links ? wird etwas legitimer nur weil mehrere es verwenden ?
(wenn mehrere leute klauen wird es doch auch nicht legaler - nur weis viele machen -.-) Der Vergleich hinkt doch aber mächtig. Hätte ich Seiten verlinkt die alle das gleiche schreiben, okay. Habe ich aber nicht. In allen wurden CollectionViews benutzt, thematisch waren sie aber teilweise völlig unterschiedlich gelegen. Das macht meinen Standpunkt schon legitimer. Weil es doch ein Zeichen ist, das im Gegensatz zu deiner Einzelmeinung (es bleibt für mich eine Einzelmeinung so lange du nichts gegenteiliges zeigst), ein kollektiver Standpunkt ist, der von vielen vertreten wird.

... und zwar das dieses objekt ein view objekt ist - haben alle geschrieben - aber alle auch missachtet Nein, haben sie eben nicht. Sie haben das geschrieben was sie denken, was ja anscheinend die allgemeine Sichtweise ist. Und in der Aussage passiert das was du oft machst. Du sagst zwar, dass du deine eigene strenge Sichtweise vertrittst, trotzdem bildest du genau diese Sichtweise auf die Beiträge ab und sagst das alle anderen das Prinzip nicht verstanden haben und es missachten. Ich verstehe nicht wie man denken kann "Hmm, alle machen das anders als ich, also müssen alle anderen falsch liegen".

die collectionview hat zwar keine referenz auf ein ui objekt - aber wie ich doch die ganze zeit selber schon sagte - view != gui Du solltest dir das Beispiel mal angucken... Es ist wieder das selektive zitieren von dir. Zusammen mit dem Beispiel ergibt der Satz eine ganz andere Sichtweise als die von dir vertretene.

zudem lass ich nichts weg - ich zitiere wenn immer alles! Ich hab nicht gesagt das du unvollständig zitierst, ich habe gesagt das du selektiv zitierst. Das was du zitierst ist natürlich komplett. Das es aber auseinem anderen Zusammenhang kommt wird bei dir nicht Rechnung getragen.

(ich zitiere mich oft selber da ich mich eh staendig wiederhol - da du den standpunkt irgendwie nicht verstehen willst

Ich verstehe natürlich das man unterschiedliche Meinungen und Standpunkte haben kann.

Der Satz der die Diskussion richtig aufgeheizt hat, ist ja immer noch dieser:

wogegen eine collectionview die items nur virtuell filtert, sortiert oder selektiert statt es richtig in der liste zu machen - daher ist die collectionview auch ein view objekt und das hat nichts in den viewmodels zu suchen...

Dieser steht erstmal fest da als Aussage. Du schreibst nirgends das diese Meinung deine eigene ist und nicht die sonst anerkannte. Und genau sowas kann ich nicht stehen lassen. Erst recht nicht wenn man seine eigene Meinung immer nur durch die eigene Meinung begründet. Es gehts mir hier fast weniger um des Thema als ums Prinzip: Einzelsichtweise gegen verbreitete Sichtweise. Ich will an dieser Stelle auch mal betonen das es auch nicht um dich als Person oder deinem Fachwissen geht - das schätze ich auch weiterhin sehr - trotz dieser Meinungsverschiedenheit 😃 Aber zurück zu der Einzelsichtweise - es gibt im Internet genug Selbstdarsteller! In vielen Blogs oder Foren stellen Leute Ihre Meinung da und akzeptieren kaum andere Sichtweisen. Das kann man machen wenn man um Politik oder Bildung diskutiert. Aber nicht wenns um Technik geht wo jeder Standpunkt mit Beweisen untermauert werden können muss. Ein Standpunkt wofür die Begründung einzig allein darin besteht, das man halt diese Meinung hat, ist wertlos für andere.

Im Prinzip ist es doch fast so als wenn irgendwer immer schlechte, unlogische, falsche Lösungsvorschläge zu einer Frage postet, und immer wieder sagt, das muss so sein weil ich es sage. Mal nen vielleicht blödes gekünsteltes Beispiel: alle benutzen Properties in C#. Einer vertritt die Meinung das man Properties nicht verwenden sollte, und stattdessen get und set Methoden schreibt. Und das stellt er dann als Antwort hin als wäre es die anerkannte Meinung. Das mein ich mit Enzelstandpunkt und allgemein anerkannter Standpunkt.

Dein Standpunkt ist natürlich nicht falsch oder schlecht und ich verstehe durch eine Argumentation durchaus wie du dazu kommst. Trotzdem ist es in meinen Augen extrem ungünstig so einen Einzelstandpunkt hier in Beiträgen zu vertreten, wo es doch drauf ankommt die allgemein anerkannte Meinung darzustellen. Das soll jetzt auch auf keinem Fall heißen das du deine Meinung nicht vertreten darfst. Ohne Meinungsfreiheit hier im Board würds die Diskussion gar nicht geben 😃

Baka wa shinanakya naoranai.

Mein XING Profil.

U
1.578 Beiträge seit 2009
vor 14 Jahren

Das würd ich einfach so machen:

  <ListBox x:Name="myList" >  
    <ListBox.InputBindings>  
      <KeyBinding Key="Delete" Command="KeyDownCommand" CommandParameter="{Binding ElementName=myList, Path=SelectedItem}" />  
    </ListBox.InputBindings>  
  </ListBox>  

wenn es mal funktionieren wuerde:

DeleteCommand ist ein ICommand im viewmodel des fensters

public class MainViewModel : ViewModelBase
{
    ...
    public ICommand DeleteCommand
    {
        get
        {
            if (_deleteCommand == null)
                _deleteCommand = new DelegateCommand(p => Delete());
            return _deleteCommand;
        }
    }
    private ICommand _deleteCommand { get; set; }
    ...
}
<Window ...>
    <ListView ...>
        <ListView .InputBindings>
            <KeyBinding Key="Delete" Command="DeleteCommand" />
        </ListView .InputBindings>
    </ListView>
</Window>

"Die Zeichenfolge "DeleteCommand" im Attribut "Command" kann nicht in ein Objekt vom Typ "System.Windows.Input.ICommand" konvertiert werden. CommandConverter kann nicht von System.String konvertieren."
(ein Binding {Binding DeleteCommand} kann ich nicht verwenden da Command kein dp ist)

wie soll ich denn an den command kommen ohne ein binding verwenden zu koennen und der string nicht richtig interpretiert wird ?

ich glaube mich zu erinnern das ich es deswegen bisher nie verwendete - ist aber schon ne weile her

auf deinen anderen text gehe ich spaeter genauer ein, wenn ich mehr zeit habe

U
1.578 Beiträge seit 2009
vor 14 Jahren

grad ma probiert:


public class KeyBinding : System.Windows.Input.KeyBinding
{
	public ICommand CommandBinding
	{
		get { return (ICommand)GetValue(CommandBindingProperty); }
		set { SetValue(CommandBindingProperty, value); }
	}

	public static readonly DependencyProperty CommandBindingProperty =
		DependencyProperty.Register("CommandBinding", typeof(ICommand), typeof(KeyBinding), new UIPropertyMetadata(OnCommandBindingChanged));

	private static void OnCommandBindingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
	{
		var keyBinding = (KeyBinding)d;
		keyBinding.Command = (ICommand)e.NewValue;
	}

	public object CommandTargetBinding
	{
		get { return (object)GetValue(CommandTargetBindingProperty); }
		set { SetValue(CommandTargetBindingProperty, value); }
	}

	public static readonly DependencyProperty CommandTargetBindingProperty =
		DependencyProperty.Register("CommandTargetBinding", typeof(object), typeof(KeyBinding), new UIPropertyMetadata(OnCommandTargetBindingChanged));

	private static void OnCommandTargetBindingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
	{
		var keyBinding = (KeyBinding)d;
		keyBinding.CommandTarget = (IInputElement)e.NewValue;
	}
}


<ListView ...>
	<ListView.InputBindings>
		<Events:KeyBinding Key="Delete" CommandBinding="{Binding DeleteCommand}" />
	</ListView.InputBindings>
</ListView>


System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=DeleteCommand; DataItem=null; target element is 'KeyBinding' (HashCode=38350037); target property is 'CommandBinding' (type 'ICommand')

dh ich muesste mir irgendwann mal was richtiges einfallen lassen so wie ich das mit den events schon habe
(Events:EventCommandName="KeyDown KeyDownCommand; KeyUp KeyUpCommand ...")