Laden...
U
Benutzerbeschreibung
Konto auf Wunsch des Benutzers gesperrt

Forenbeiträge von userid14268 Ingesamt 1.578 Beiträge

09.12.2010 - 13:46 Uhr

Für Maps scheint es nur für die Handyversion zu sein, right?
Also bleibt für PCs nur Google Earth.

06.12.2010 - 14:15 Uhr

Hajo so eng würde ich es nicht sehe, es stimmt schon das ein paar Controls fehlen, nur sobald man diese einmal hat ist man irgendwann so weit das man nichts mehr vermisst.
Mühsam finde ich WPF keineswegs, wenn man sich einmal mit den "Binding Geschichten" (:D) angefreundet hat geht alles recht flott von der Hand.

Anm.d.R. Der Autor dieses Beitrags entwickelt WPF seit ende 2008 und hat womöglich einfach nur gut reden 😁

//Edit 1: Smilies aktiviert.
//Edit 2: Zu doof für alles.

04.12.2010 - 09:59 Uhr

"NewsLetterItemName" und "NewsletterItemID" kannst du kürzen zu "Name" und "ID",
"Newsletter" ist das Item bereits, sind also Redundante Informationen

2.
Ich würde an deiner Stelle keine Newsletter Gruppen erstellen, eher die Information zu welcher Gruppe ein Newsletter gehört in form eines Properties, und dann einfach die Liste selbstständig danach Gruppieren lassen.

3.
Zum Thema Speichern und Laden
Da reichen schon Wenige Informationen, z.b.
Tabelle 1: NewsLetters: Id, Name, Description, GroupName
Tabelle 2: Users: Name, NewsLetterIds

Lange Rede gar kein Sinn, hier mal Pseudocode:

public class Newsletter : INotify....
{
    public int ID { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public string GroupName { get; set; }
    public bool IsSelected { get; set; }
}
public class User : INotify....
{
    public string Name { get; set; }
    public ObservableCollection<Newsletter> Newsletters { get; set; }
}

Nun baust du dein Fenster auf
Wir gehen davon aus das du bereit ein User hast (Wie das bei dir aufgebaut ist wissen wir ja nicht).

D.h. du gibst den User alle vorhandenen Newsletter in seiner "Newsletters" Collection und setzt alle auf "IsSelected" die vorher schon ausgewählt waren.

Diese Liste von Newslettern bindest du an eine ListView, in den CellTemplates erstellst du dann entsprechend CheckBox.IsSelected gegen den IsSelected, und TextBlock.Text gegen Name und noch ein TextBlock.Text gegen Description.
Zudem definierst du eine GroupDescription und lässt die Gruppen nach den GroupName erstellen, das lässt du dann auch im GroupTemplate entsprechend anzeigen.
Nachdem der Benutzer das Fenster schloss, schmeißt du einfach alle !IsSelected aus der Newsletters Collection und du kannst den User neu abspeichern.

Hier auch mal Pseudo davon:

<Window ...
        xmlns:ComponentModel="clr-namespace:System.ComponentModel;assembly=WindowsBase">
        ...>
    <Window.Resources>
        <CollectionViewSource x:Key="Newsletters" Source="{Binding Newsletters}">
            <CollectionViewSource.GroupDescriptions>
                <PropertyGroupDescription PropertyName="GroupName" />
            </CollectionViewSource.GroupDescriptions>
            <CollectionViewSource.SortDescriptions>
                <ComponentModel:SortDescription PropertyName="Name" Direction="Ascending" />
            </CollectionViewSource.SortDescriptions>
        </CollectionViewSource>
    </Window.Resources>

    <ListView ItemsSource="{Binding Source={StaticResource Newsletters}}">
        <ListView.GroupStyle>
            <GroupStyle>
                <GroupStyle.ContainerStyle>
                    <Style TargetType="{x:Type GroupItem}">
                        <Setter Property="Margin" Value="0,0,0,5" />
                        <Setter Property="Template">
                            <Setter.Value>
                                <ControlTemplate TargetType="{x:Type GroupItem}">
                                    <StackPanel>
                                        <TextBlock FontWeight="Bold" Text="{Binding Name}" Margin="5,0" Foreground="Blue" />
                                        <ItemsPresenter />
                                    </StackPanel>
                                </ControlTemplate>
                            </Setter.Value>
                        </Setter>
                    </Style>
                </GroupStyle.ContainerStyle>
            </GroupStyle>
        </ListView.GroupStyle>
        <ListView.View>
            <GridView>
                <GridViewColumn>
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <CheckBox IsChecked="{Binding IsSelected}" />
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>
                <GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}" />
                <GridViewColumn Header="Description" DisplayMemberBinding="{Binding Description}" />
            </GridView>
        </ListView.View>
    </ListView>
</Window>
04.12.2010 - 09:26 Uhr

Korrekt.
In Microsoft.Win32 ist nur der Open und Save Dialog.
http://msdn.microsoft.com/de-de/library/microsoft.win32(v=VS.100).aspx
Der BrowseFolder, ColorPicker und FontPicker ist nur in Forms.

Ich selber habe zu dem Zweck diese Dialoge in mein DialogService gewrappt, sdass ich in meiner WPF Applikation nicht entscheiden muss ob es Win32 oder Forms ist, zudem Color und "Font" gleich richtig konvertiert ist.
Intern verwende ich dann alle pauschal aus Forms.

GitHub zum IDialogService

Ich persönlich finde es schade das MS noch nicht alle bereit gestellt hat, kommt eventuell noch, sie man es an den Calendar Control gesehen hat (TimePicker fehlt aber weiterhin)
Wenn man so überlegt wie viel Custom Controls man in WPF noch braucht für die alltäglichen Sachen...

01.12.2010 - 07:49 Uhr

BTW ein DoubleClickBehavior hab ich schon lang:
GitHub link to the DoubleClickBehavior source

Bsp.:

<TextBlock Text="Demo Text" Mvvm:DoubleClickBehavior.Command="{Binding ChoosedCommand}" />
28.11.2010 - 09:11 Uhr

Ich benutze keine Container, ich benutze nur einen ServiceLocator...

23.11.2010 - 08:39 Uhr

Unter Windows 7 ist es obsolet, da gibt es das Snipping Tool.

08.11.2010 - 09:09 Uhr

Ein CustomControl wirst du schon machen müssen, ist ja kein Akt, so wie du es beschrieben hast ist es korrekt.

Ein "Durchreich Property" gibt es nicht, das siehst du richtig, aber das ist aber auch gut so, keinen außer dem CustomControl selber geht es etwas an wie es intern aufgebaut ist 😉

07.11.2010 - 21:36 Uhr

Ups - hab nix gesagt 😄

07.11.2010 - 21:34 Uhr

Die WPF Lokalisierung ist am einfachsten über ResourceDictionaries zu lösen, wie es schon geschrieben wurde.

Hier habe ich vor einiger Zeit mal ein Beispiel erstellt: Localization: Just a translation easy and fast

In den Satellite Assemblies die man z.B. mit LocBaml erstellen kann ist auch nichts mit diesen resx Dateien, vielmehr werden da komplette Xamls als Ressourcen neu eingelesen und die vorhandenen so überschrieben (beim laden einer dll).

07.11.2010 - 19:47 Uhr

Ich habe in meinem Projekt mehrer Fenster die über events miteinander kommunizieren.

Sind es sehr viele Fenster? In solch einen Fall könnte sich auch das Mediator pattern anbieten, ist besser alles alles miteinander zu verflechten 😁

07.11.2010 - 19:43 Uhr

Die Angabe vom Mode beim Binding ist übrigens überflüssig. Beim TextProperty der TextBox ist das per Default so.

Meeep, falsch, der Default ist an der stelle LostFocus 😉Binding.UpdateSourceTrigger

The TextBox.Text property has a default UpdateSourceTrigger value of LostFocus.

Daran muss man denken wenn man Enter auf ein Button hat und in der Box tippt und dann Enter drückt (Wie bei einer Search bar) dann wird der Text nicht aktualisiert es sei den man ändert es auf PropertyChanged oder klickt auf den Button

07.11.2010 - 13:35 Uhr

Also gegen ein enum Yes|No hätte ich nichts, nur die Namensgebung YesNoEnum ist der wirkliche Coding Horror

07.11.2010 - 09:48 Uhr

Tja, dir fliegt BitmapFrame um die Ohren, ich frage mich sowieso wieso du ein es erstellst. Hatte ich dich auch gefragt 😉

Weise einfach nur das BitmapImage zu und fertig.

BitmapImage bm = new BitmapImage();
bm.BeginInit();
bm.UriSource =  new Uri("icon.bmp");
bm.EndInit();
this.Icon = bm;

Das BitmapFrame stellt laut MSDN ein paar Methoden mehr bereit die im BitmapImage nicht vorhanden sind, das brauchst du doch gar nicht.

Bleibt aber noch die Frage:
Warum willst du das Icon aus dem Code heraus setzen?

06.11.2010 - 22:07 Uhr

Da hat einer die Docu nicht gelesen, hier nochmal für dich:
BitmapImage-Klasse

BitmapImage implementiert die ISupportInitialize-Schnittstelle, um die Initialisierung für mehrere Eigenschaften zu optimieren.**Eigenschaftenänderungen können nur während der Objektinitialisierung erfolgen.Rufen Sie BeginInit auf, um zu signalisieren, dass die Initialisierung begonnen wurde, und rufen Sie EndInit auf, um zu signalisieren, dass die Initialisierung abgeschlossen wurde.**Eigenschaftenänderungen nach der Initialisierung werden ignoriert.

Siehe den C# Beispielcode auf der Seite.

//Dazu
Warum willst du es aus dem Code heraus machen? Und wozu brauchst du das BitmapFrame?

05.11.2010 - 13:32 Uhr

Ich erinnere mich an meine Einstellunsprozedur.

Zuerst wurde ich mit einem Entwickler zusammen gesetzt, der hatte ein paar Code ausdrucke wo ich ein Fehler finden sollte, da hatte ich 1 von 5 ^^. (Nur C++)

Danach hieß es, den Rest des Tages eine kleine Programmieraufgabe zu lösen, eine Konsolen Applikation die ein Irrgarten aus einer Text Datei aus liest, und dann selbständig den Weg findet. Angesetzte Zeit waren 4h wenn ich mich recht erinnere.

Am ende wurde zusammen (zu dritt) der Code durch gesehen um zu schauen was ich wie gelöst habe.

So kam ich dann in die "nächste Runde" und zwar eine größere Aufgabe in einer normalen Arbeitswoche zu lösen, essen und Unterkunft wurde von der Firma gestellt.

Joa, das ist nun fast 4,5 Jahre her.

05.11.2010 - 10:59 Uhr

Was ich, als ich lernte, auch gerne gemacht habe ist das ich das Template was ich machen möchte in einem Button Template erstellte und rum probierte, das konnte VS immer korrekt im Designer anzeigen.

<Button Content="Content">
    <Button.Template>
        <ControlTemplate>
            <Grid>
                <!-- Hier herum spielen -->
                <ContentPresenter />
            </Grid>
        </ControlTemplate>
    </Button.Template>
</Button>

Sobald das Template dann fertig war habe ich es an seinen finalen Platz geschoben und hatte nur noch Kleinigkeiten an zu passen.

04.11.2010 - 20:12 Uhr

Zu diesem Thema hab ich ein paar Themen, siehe meine Seite die Localization Kategorie.
Da ist unter anderen eine kleine Anleitung wie man sehr leicht kleine Applikationen übersetzt.

Eine Anleitung mit den Satellite Assemblies (MUI) habe ich derzeit leider nicht.

01.11.2010 - 09:26 Uhr

Das kann ein sehr komplexes thema werden, womit sich bei MS ganze Teams beschäftigen 😉
Wenn man mal schaut, selbst Word schafft es nicht Japanisch korrekt um zu brechen, [WPF/Forms] Controls erst recht nicht. Auch im Chinesischen sind immer wieder falsche Breaks enthalten.

29.10.2010 - 11:49 Uhr

Du sagst du blendest den Designer aus ?

Im normalfall ist er jedoch noch an im Hintergrund.

Was ich da immer mache ist bei XAML Dateien Öffnen mit -> Quellcode Editor (Text)
das dann auf Standard stellen und alle Designer Fehler sind erstmal geschichte 😃

André

Bei FullXamlView nicht, da wird der Designer nur geladen wenn man es aufklappt.
Was was du da manuell machst kannst du auch als Standard definieren.
Der vorteil der FullXamlView ist das es auch deutlich schneller öffnet.

@MrSparkle

  • Control Ctors werden vom Designer ausgeführt,
  • Resourcen die durch sourcecode hinzugefügt werden können nicht aufgelöst werden,
  • Wenn Controls aus 3rdParty dlls kommen kann es auch vor kommen das er die Controls zur Designtime nicht findet
27.10.2010 - 15:16 Uhr

Wo hast du das HierarchicalDataTemplate stehen? ItemsTemplate? Resources?

27.10.2010 - 07:34 Uhr

ich kann über position.X und position.Y auf die einzelnen Werte zugreifen...

Aber nicht setzen, nur lesen, es sei denn du machst was ich bereits schrieb:

Zum setzen der Position dann entweder ein neuen Vector erstellen, oder Position nem neuen Point zuweisen.

D.h. du kannst die werte einzeln aus den Point lesen, aber nicht setzen, zum setze muss du die ganze Point struktur überschreiben.

25.10.2010 - 12:19 Uhr

Genau.
Die Maßeinheiten in WPF sind nicht Pixel sonder eigene einheiten, standardmäßig sind es 96pixel/zoll

25.10.2010 - 10:07 Uhr

Ich dacht das wäre hier alles schon genug breit getreten -.-

Kannst mich ruhig adden.

25.10.2010 - 07:43 Uhr

Hat der "Vector" noch mehr werte außer die Position? Wenn nein warum, nimmst du nicht einfach ne Point Struktur?
Wenn der Vector noch mehr hat kannst du auch die Point Struktur nehmen um X und Y weg zu kapseln.
Falls du die position einfacher haben möchtest kannst du auch read only properties anbieten wie in den folgenden Beispielcode.
Zum setzen der Position dann entweder ein neuen Vector erstellen, oder Position nem neuen Point zuweisen.

public class Vector
{
    public Vector(Point position)
    {
        Position = position
    }

    public Vector(int x, int y)
        : this(new Point(x, y))
    { }

    public Point Position { get; set; }

    public int X
    {
        get { return Position.X; }
    }

    public int Y
    {
        get { return Position.Y; }
    }
}

PS. Das kommt mir alles sehr anfängermäßig vor.

20.10.2010 - 15:51 Uhr

Ach Silverlight, das dreckszeuch ^^

Da gibt es HitTest so nicht, es gibt aber System.Windows.Media.VisualTreeHelper.HitTest laut internet.
Eventuell kannst du mit dem Ergebnis etwas anfangen, wenns schon das korrekte Control beinhaltet kannste dann mit dem VisualTreeHelper hoch klettern bis du das TreeViewItem hast um dann IsSelected zu setzen.

//Dazu
Ist in Silverlight Rechtsklick überhaupt möglich? Ich dachte dann kommt immer das SL context Menü und kein Control bekommt davon mit?!

20.10.2010 - 14:43 Uhr

Rechtsklick selektiert solch ein Item nicht, das ist korrekt.
Ich habe das in meiner EnhancedTreeView bereits gelöst, siehe "EnhancedTreeView_PreviewMouseRightButtonDown"

18.10.2010 - 13:12 Uhr

Das einzigste was mir derzeit einfallen würde wäre ein Custom Panel (so wie mein UniformWrapPanel), ist mir aber zuviel Arbeit 😁

18.10.2010 - 13:10 Uhr

Ob es nun die echte TreeView ist, oder ein Baum der nur im Code ist -> Die handhabe ist genau die selbe.

Erstell dir einfach ein Baum im Code, und arbeite mit diesen, genau so wie du es mit der TreeView machst.
Die echte TreeView lässt du dann einfach dagegen Binden und fertig.

Du hast dein ModelViewProject, das hat eine Liste von ModelViewStructur, und das wiederum hat eine liste von ModelViewFile.
Damit arbeitest du, kannst da suchen, einfügen, entfernen, trallalla - ohne das du dir über die TreeView gedanken machst

18.10.2010 - 09:07 Uhr

Hi,

Ich bräuchte mal eine Idee.

Mein Ziel ist es eine TreeView auf 3 Columns auf zu teilen ohne sie im Code splitten zu müssen.

Anforderung:

  • Ein Baum im Code soll auf 3 TreeViews in 3 Columns (Grid) aufgesplittet werden.
  • Die Items müssen links nach rechts von oben nach unten Sortiert sein.
  • Die TreeView's müssen sich wie normale TreeViews verhalten.

Bisher splitte ich es im Code, einfach Item Anzahl / 3 und dann in 3 Bäume aufteilen.

Das hat den Nachteil der bearbeitung im Code (habe derzeit immer Hilfsmethoden dafür) und das Selektionsverhalten ist etwas blöd, es ist immer eines Pro column auswählbar, es soll sich aber so verhalten wie das normale TreeView.
Ich selber benutze meine EnhancedTreeView um multiselekt zur verfügung zu stellen, ich kann aber leider nicht mit Shift von einen Baum zum, nächsten wechseln, ledliglich immer innerhalb eines Baumes.

Ich habe auch schon ein UniformGrid versucht mit fester Columns angabe, nur dann werden auch die Item Height geshared, und die Sortierung ist auch verkehrt.

Jemand n Vorschlag?

BR
CSL

15.10.2010 - 07:53 Uhr

Hatt deine TreeViewItemProps Klasse vorher auch von DependencyObject abgeleitet?

static void FolderExpanded(object sender, RoutedEventArgs e)

Wasn das für ne Methode und was macht die?

14.10.2010 - 20:35 Uhr

Deine int values sind anders, vorher hattest du immer 1 als standard und auf 0 gefragt, jetzt hast du 0 als standard und fragst auch auf 0.
Eventuell funktionerte es bereits nur Value="0" traf einfach nie zu 😁

14.10.2010 - 19:58 Uhr

Das Problem ist der StackPanel, der staucht die Childs nicht und die ScrollViewer bekommen so viel Platz wie sie wollen.
Nimm n DockPanel.

14.10.2010 - 16:09 Uhr

Sind es verschachtelte ScrollViewer? Das macht natürlich kein Sinn, da der innere ja durch den äußeren genug Platz bekommt und entsprechend nichts zu Scrollen hat.

PS.
Es gibt auch noch die Horizontal|VerticalScrollBarVisibility properties 😉

14.10.2010 - 15:20 Uhr

Ich seh jetzt erst, TreeViewItemsProps beinhaltet ein Attached property, ich hätte mal genauer lesen sollen.

Auf jeden fall sucht er das TreeViewImage im TreeViewItem.
Aber er muss das TreeViewItemsProps.TreeViewImage im TreeViewItem suchen, da es ein attached ist und kein eigenes Property.

"Path=(local:TreeViewItemProps.TreeViewImage)" ist also die korrekte schreibweise 🙂

14.10.2010 - 15:05 Uhr

IWindowServices windowService = ServiceLocator.Resolve<IWindowServices>();
windowsService.ShowView<IView>();

Genau da sieht man das Problem, dein ViewModel muss "IView" kennen, und alle Views benötigen ein eigenes Interface - finde ich ziemlich unsauber.

Ich geh von mindestens 3 Assemblies aus:

  • App.exe
  • Views.dll
  • ViewModels.dl

Die exe kennt alle beide, und die Views.dll kennt die ViewModels.dll. Aber die ViewModels.dll kennt die Views.dll nicht, also auch nicht deren Interfaces.

Am Ende sollten die ViewModels komplett alleine stehen können, ohne das es eine View gibt - das ist ja der Vorteil der Trennung.

//Dazu:
"Was ich nur nicht will, ist das ich alle View-ViewModel kombinationen irgendwo nochmal explizit angeben muss... "
Du musst ja keine Paare angeben, es reicht ja wenn du einfach nur alle Views mit einem key kennst, das kannste zb über ne xml Datei regeln, die ViewModels müssen dann halt den key angeben welche View sie gerne hätten.
Du könntest den WindowService so gestalten das er ein key nimmt, und dann das entsprechende Fenster (per Reflection?) selber aus einer dll fingert, anhand des Key welches den View Namen repräsentiert.

14.10.2010 - 14:47 Uhr

Also ich habe es so wie ich schrieb über eine methode im Service:

IWindowService windowService = ServiceLocator.Resolve<IWindowService>();
windowService.Register<FirstView, FirstViewModel>();

FirstView muss an der stelle ein "Window" objekt sein (wozu also ein interface 😉) und FirstViewModel in meinem fall ein "WindowViewModel" (ich habe für ViewModels die zu einem Fenster gehören ein separaten base
ObservableObject <- für INotifyPropertyChanged only
WindowViewModel : ObservableObject <-- Zusätzliche virtuelle Loaded, Closing und Closed Methoden)

Es gibt immer mindestens eine Zentrale stelle wo man View und ViewModel typen kennt, entweder in der Views assembly, oder in der exe assembly selber.

Man kann aber auch Fenster ohne ViewModel registrieren

IWindowService windowService = ServiceLocator.Resolve<IWindowService>();
windowService.Register<FirstView>("FirstView");

Dann muss das ViewModel aber sagen welches Fenster es gerne hätte:

if (windowService.ShowDialog("PersonInfoNameView", this, infoViewModel) == true)

PS. Bei meiner Lösung muss man aber das WindowService mit dem Singleton Lifetime registrieren, damit die Paare nicht verloren gehen!

In meinen UnitTests habe ichs dadurch recht einfach um Eingaben zu faken:

ServiceLocator.Register<IWindowService>(new TestWindowService());

[TestMethod]
public void OpenFileCommand_UserGivesNamePressOkay_AddPersonToList()
{
    // User gives a name and press OK
    TestDataContext.Record<IWindowService>("ShowDialog", parameter =>
    {
        PersonInfoNameViewModel viewmodel = (PersonInfoNameViewModel)parameter[1];
        viewmodel.Name = "My Name";
        return true;
    });
 
    MainViewModel mainViewModel = new MainViewModel();
    mainViewModel.CreateNewPersonCommand.Execute(null);
 
    Assert.IsTrue(mainViewModel.Persons[0].Name == "My Name");
}
14.10.2010 - 14:18 Uhr
'TreeViewImage' property not found on 'object' ''TreeViewItem'

<< Sagt eigentlich alles 😉
Wo ist dein "TreeViewItemProps" innerhalb der TreeViewItems definiert? Im DataContext?

14.10.2010 - 13:59 Uhr

Hm?

Das ViewModel was ich im Beispiel erstellt habe ist das ViewModel welches man benutzt, das brauchst du so oder so. Und über die Services arbeitet man auch stets.

Etwas ausführlicher:

PersonInfoNameViewModel infoViewModel = new PersonInfoNameViewModel();

IWindowServices windowService = ServiceLocator.Resolve<IWindowServices>();
if (windowService.ShowDialog(this, infoViewModel) == true)
{
    string name = infoViewModel.Name;
    // ...
}

Wie man unschwer erkennt hat man kein verweis auf irgend eine view, kein typen, kein namen, nix.
("this" ist an der stelle auch ein ViewModel, und zwar das des owners)
Der Service sucht sich die zum VM passende View, setzt den DataContext und den Owner.
Wenn man möchte kann man im Container auch ein TestWindowService registrieren, schon kann man usereingaben aus den UnitTests heraus faken 😉

//Dazu: Eventuell haben wir uns nur Missverstanden 😉

14.10.2010 - 13:52 Uhr

Nö, machst bestimmt nix falsch, der Designer ist einfach der letzte Müll, lass ihn einfach zu (und stell Xaml in den Settings auf "full xaml view", dann öffnet sich das Xaml Fenster schneller).

PS. lass dein TreeViewItemProps von DependencyObject ableiten.

14.10.2010 - 13:14 Uhr

das wäre dann zB PseudoCode: resolve<View>().ViewModel.ShowDialog();

Is ja gruselig.

Man gehe davon aus das die Views und die ViewModels in unterschiedlichen Assemblies liegen, die View assembly kennt die ViewModel assembly, aber nicht umgekehrt, dh die ViewModels sollten komplett unabhängig von den Views sein, sie kennen den Typen der View nicht, also ein "Resolve<View>" geht nicht.
Diese aunabhängigkeit erreicht man so wie ich das bereits schrieb 😉
Ich persönlich arbeite ausschließlich mit den ViewModels, sei es als Owner oder als DataContext
ShowDialog(this, new DemoViewModel());
ShowDialog(new DemoViewModel());
usw.

14.10.2010 - 12:05 Uhr

Richtig verstanden hab ich dein Text nicht ^^ aber ich kann dir sagen was ich in mein WindowService anbiete.
Und zwar dass man beim erstellen des WindowService View<->ViewModel paare registriert, und sobald ein ShowDialog oder ähnliches aufgerufen wird, sucht sich der Service selbstständig die View und Packt das ViewModel in dessen DataContext.

Die implementation findest du hier: http://github.com/DavidWCSL/DW.MVVMStd/tree/master/DW.MVVMStd/Services/
Im speziellen: http://github.com/DavidWCSL/DW.MVVMStd/blob/master/DW.MVVMStd/Services/Interfaces/IWindowService.cs und http://github.com/DavidWCSL/DW.MVVMStd/blob/master/DW.MVVMStd/Services/Implementations/WindowService.cs

Der aufruf ist dann einfach:

ServiceLocator.Register<IWindowService>(new WindowService());
// ...
IWindowService windowService = ServiceLocator.Resolve<IWindowService>();
windowService.Register<FirstView, FirstViewModel>();
windowService.Register<SecondView, SecondViewModel>();

// in der späteren Benutzung dann einfach:
IWindowService windowService = ServiceLocator.Resolve<IWindowService>();
if (windowService.ShowDialog(this, new SecondViewModel()) == true)

Man kann die Fenster auch mit nem Namen registrieren und aufrufen, nur ich bevorzuge die paare, da braucht das VM nicht wissen welche View verwendet wird => absolute unabhängigkeit.

//Dazu
Siehe auch meine (derzeit unvollständige) Documentation

13.10.2010 - 16:06 Uhr

Man siehe hier: http://msdn.microsoft.com/de-de/library/ms788717.aspx
Dort verwenden die "SelectedBackgroundBrush" aber haben das als eigene Farbe definiert -> Also Nein, es gibts nichts festes.

Das beste was man machen kann ist die Fabe selber raus fingern, und dann eine Classic.xaml, Aero.NormalColor.xaml usw im Template ordner zu definieren (und Generic.xaml als fallback).

13.10.2010 - 14:29 Uhr

Template überschreiben und selber zeichnen.
Das Item ist dann einfach ein Border wo du im IsMouseOver den Background und BorderBrush setzt. Dürfte relativ einfach sein.

13.10.2010 - 14:27 Uhr

Hallo,

also irgendwie komme ich nicht wirklich weiter 😦
Ich glaube MVVM kann ich bei mir nicht verwenden.

Was ich bisher so über das MVVM gelesen habe benötige ich hierfür für jede Ebene ein neues ViewModel für eine andere Klasse. Also z.B Ebene 1 -> Klasse 1; Ebene2 -> Klasse2; Ebene3 -> Klasse 3 etc.

Du benötigst nur unterschiedliche ViewModel wenn sie auch unterschiedliche typen repräsentieren.

Und das mit den Templates habe ich aus dem Forum und Beispielanwendungen jetzt so verstanden, dass ich für jede Hierachie ein HierachieTemplate benötige und auf der letzten Ebene dann ein DataTemplate.

Aber mein Baum ist leider nicht so aufgebaut. Ich habe 3 Klassen.

Klasse 1 Projekt
Klasse 2 Verzeichnis
Klasse 3 Datei

Der Baum könnte wie folgt aussehen

  
-Projekt (Ebene 1)  
   - Verzeichnis (Ebene 2)   
      - Verzeichnis (Ebene 3)  
         - Datei1 (Ebene 4)  
         - Datei2 (Ebene 4)  
      - Verzeichnis (Ebene 3)  
         - Datei1 (Ebene 4)  
         - Datei2 (Ebene 4)  
      - Datei1 (Ebene 3)  
      - Datei2 (Ebene 3)  
  

Also ähnlich dem Windowsexplorer.
Die Verzeichnistiefe kann unendlich sein und ist dynamisch.

Is doch kein problem, durch den DataType sucht sich automatisch der entsprechende template selber, du kannst im code schachteln wie du lustig bist

In einem Buch habe ich ein Beispiel gefunden zum Lazy Loading und TreeView entdeckt.
Die haben den Baum im c# Code auch manuell aufgebaut (Windowsexplorer nachgebaut).

Die haben jedes Objekt (Verzeichnis bzw. Datei) der Header- Eigenschaft des entsprechenden TreeViewItems zugewiesen.

Is ja gruselig, wasn das für n scheußliches Buch? Das ist so MFC/Forms like.

Ich habe das auch mal so gemacht und in meiner XAML Datei habe ich jetzt folgendes drin stehen:

  
<TreeView HorizontalAlignment="Left" Margin="0" Name="tvProjects" VerticalAlignment="Stretch" Width="200"   
                  TreeViewItem.Expanded="treeViewItem_Expanded">  
            <TreeView.Resources>  
                <HierarchicalDataTemplate DataType="{x:Type local:Project}">  
                    <StackPanel Orientation="Horizontal">  
                        <Image Width="16" Height="16" Margin="3,0" Source="Images\Project.png" />  
                        <CheckBox Content="{Binding ProjectName}" Checked="treeViewItem_Checked" />  
                    </StackPanel>  
                </HierarchicalDataTemplate>  
            </TreeView.Resources>  
        </TreeView>  
  

Was hast du gemacht? TreeViewItems manuell aufgebaut? Lass den quatsch.

Also für die Projektauflistung funktioniert das schonmal. Aber kann ich jetzt auch ohne ViewModel auf meine ausgewählten Elemente im Baum zugreifen?

Also ich müsste ja dann aufjedenfall eine IsSelected Eigenschaft in der Klasse Project implementieren. Aber wie kann ich den Wert dann abrufen bzw. bekomme meine ganzen TreeViewItems die gechecked sind ? Kann ich das so auch über diesen ItemContainerStyle machen ?

Binde IsSelected im ItemContainerStyle wie winSharp schon schrieb, und im Code holstr du einfach die Items rekursiv.
IsChecked kannst du im normalen Template ebenfalls binden und abfragen.

11.10.2010 - 19:25 Uhr

Schnapp dir ein DoubleCLick attached behavior, zb das hier: DoubleClickBehavior und hänge das an den ItemContainerStyle, dann kannst du in den Template packen was du möchtest 😉

Das könnte so aussehen:

<Toolkit:EnhancedTreeView.ItemContainerStyle>
    <Style TargetType="{x:Type Toolkit:EnhancedTreeViewItem}">
        <Setter Property="Mvvm:DoubleClickBehavior.Command" Value="{Binding DataContext.ChooseItemCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}" />
    </Style>
</Toolkit:EnhancedTreeView.ItemContainerStyle>

Mein DoubleClickBehavior reicht dem Command den DataContext des Containers weiter, also die Daten.
und meine EnhancedTreeView hab ich für Multiselect 😉

09.10.2010 - 16:49 Uhr

Also ich finde auch das es Aufgabe der Application klasse ist zu entscheiden welches Hauptfenster hoch kommt.

D.h. erst ein Log-in screen, und danach sobald das erfolgreich geschlossen ist das Konkrete Hauptfenster.

Achtung: Wenn du das machst ist für die Application klasse der Log-in Screen das Hauptfenster und beendet sich sofort wenn dies geschlossen wird, du musst bei dieser Lösung den ShutdownMode umstellen.

07.10.2010 - 18:24 Uhr

Also ich musste fluxys Beitrag auch mehrmals lesen - sehr verwirrend geschrieben 😁

07.10.2010 - 17:35 Uhr

Das geht leider nicht.
Die Items müssen in einer gemeinsamen Liste geführt werden, mit nem gemeinsamen Base, ne klasser oder n Interface.

fluxy (s.o.) hatte genau das selbe Problem.

07.10.2010 - 09:30 Uhr

Befehl? Was is denn ein Befehl? CType ist eine Funktion, nichtmal ein schlüsselwort -.-