Laden...
I
ill_son myCSharp.de - Member
Leipzig Dabei seit 03.09.2009
Benutzerbeschreibung

Forenbeiträge von ill_son Ingesamt 227 Beiträge

30.06.2020 - 13:21 Uhr

Hallo,

ich habe zwei Anwendungen, die einige Views gemeinsam verwenden. Diese wollte ich deshalb in eine Library auslagern.

In einem der Controls befindest sich ein ItemsControl , dessen ItemsTemplate ich verwende.


<ItemsControl.ItemTemplate>
     <DataTemplate DataType="{x:Type ...}">

    </DataTemplate>
</ItemsConrol.ItemsTemplate>

Soll ich den verwendeten DatenTyp mit in der Library definieren? Mir fehltein bisschen die Idee, wie ich das sauber löse.

Grüße, Alex

22.06.2020 - 17:46 Uhr

Danke, das schaue ich mir mal an.

22.06.2020 - 11:35 Uhr

Hallo folgende Frage:

ich habe eine abstrake Basisklasse, von der ich andere Klassen ableite. Gemeinsamkeit aller Klassen ist, dass ihr Inhalt durch byteweise Daten bestimmt wird, die ich aus einem angeschlossenen Gerät bekomme. Nun möchte ich aus einer bestimmten Anzahl an Bytes die Klasse instanzieren und gleich noch auf eventuelle Datenfehler prüfen. Am liebsten mit einer TryParse-Methode, aber die müsste ich dann komplett in jeder abgeleiteten Klasse neu implementiern, was nicht schön ist, weil ich dann bei einer Änderung in der Basisklasse alle abgeleiteten Klassen anfassen müsste. Momentan übergebe ich das ByteArray in den Konstruktor und setzte am Ende eine IsValid Variable.

Gibt es einen eleganteren "offiziellen" Weg dafür?

Grüße, Alex

06.11.2019 - 14:10 Uhr

Hallo gfoidl,

vielen Dank für deine Mühe. Damit, denke ich, sollte das Thema gelöst sein. Zu den Arrays, ich hab schon gemerkt, dass die nicht so "handy" sind. Leider liefern die Treiberfunktionen die Daten in diesem Format. Ich hab mir aber was gebastelt/recherchiert, dass mit Hilfe von LINQ praktische Listen daraus macht.

Falls jemand mal in die Verlegenheit kommen sollte:


private double[] GetColumn(double[,] array, int columnNumber)
{
    return Enumerable.Range(0, array.GetLength(0)).Select(x => array[x, columnNumber]).ToArray();
}

public double[] GetRow(double[,] array, int rowNumber)
{
    return Enumerable.Range(0, array.GetLength(1)).Select(x => array[rowNumber, x]).ToArray();
}

Grüße und danke nochmals,

Alex

06.11.2019 - 09:20 Uhr

Hallo gfoidl,

_Daqmx ist die Instanz einer Klasse, die ich geschrieben habe. Sie kapselt den Zugriff auf die Karte und stellt mir die Funktionalitäten bereit, die ich für die Messung benötige. Unter DAQmx und APM habe ich auf der Seite von NI was gefunden. Ich schaue mir das mal an, vielleicht ist das ein Einstieg.

Grüße, Alex

05.11.2019 - 17:45 Uhr

Hallo gfoidl,

erst einmal danke für den ausführlichen Exkurs.

ich arbeite mit dem DAQmx von National Instruments, wenn dir das ein Begriff ist. Dieser unterstützt auch .NET. Ich habe eine Messkarte, mit dieser erzeuge ich einen Sinus unterschiedlicher Frequenz (Sweep) und messe für jede Frequenz einige Perioden. Das Erzeugen des Signals benötigt kaum Zeit, weil es auf der Karte passiert. Man muss den Vorgang nur initialisieren, aber da die Frequenzen recht niedrig sind, benötigt die Funktion, die die Messwerte holt ihre Zeit. Daten werden als double[,] zurückgegeben.

Im Prinzip durchlaufe ich eine for-Schleife derart:


public async Task<List<FrequencyStepResult>> Sweep(CancellationTokenSource cts, IProgress<FrequencyStepResult> progress)
{
    List<FrequencyStepResult> result = new List<FrequencyStepResult>();
    if (IsHardwareReady)
        await Task.Run(() =>
        {
            for (int i = 0; i < FrequencySteps.Count && !cts.IsCancellationRequested; i++)
            {
                 FrequencyStepResult stepResult = PerformFrequencyStep(OutputMagnitude, FrequencySteps[i]);
                 result.Add(stepResult);
                 progress?.Report(stepResult);
             }
       });

    return result;
}
        
private FrequencyStepResult PerformFrequencyStep(double magnitude, double frequency)
{
      double duration = 5 / frequency; //at leat 5 periodes
      if (duration < 1)
           duration = 1;

      int sampleRate = (int)(20 * frequency);
      if (sampleRate < 1000)
           sampleRate = 1000;

      int samples = (int)Math.Ceiling(duration * sampleRate);

       _DAQmx.StartSinusOutput(magnitude, frequency);
            
       double[,] data = _DAQmx.ReadSequence(sampleRate, samples);
       
       _DAQmx.StopOutput();

       return new FrequencyStepResult(frequency, data);
}

Grüße, Alex

05.11.2019 - 14:03 Uhr

Hallo,

danke für Eure Antworten.

@gfoidl: Das heißt für mich, dass ich, anders als Alf sagt, doch besser einen eigenen Thread erstellen sollte, denn wie hier beschrieben, nutzen Tasks den Thread Pool. Stimmt das so?

05.11.2019 - 09:54 Uhr

Hallo,

in meiner Anwendung soll eine Kommunikation mit einer Messhardware stattfinden. Das Ganze sieht so aus, dass nacheinander verschiedene Signale erzeugt werden und jeweils eine Messung durchgeführt wird. Gesamtdauer etwa halbe bis eine Minute. Zwischendurch wären Statusmeldungen mit Zwischenergebnissen ganz nett. Jetzt stellt sich mir die Frage der Implementierung. Thread mit entsprechenden Events oder await Task mit Progress? Ich habe mal irgendwo gelesen, Backgroundworker sei seit async Task "obsolet". Aber mal grundsätzlich, wann Thread und wann Task?

Grüße, Alex

03.04.2019 - 09:22 Uhr

Wenn ich dich richtig verstehe, müsste ich also anstatt mein VM zu Serialisieren aus dem ViewModel einen wie auch immer gearteten Datensatz generieren und den spiechern und beim Rücklesen aus diesen Daten dann das VM füttern?

03.04.2019 - 08:34 Uhr

Ich habe zum Beispiel eine Liste von ClassA aus der wähle ich mir einen Eintrag aus und es ist wichtig, welcher das ist, da am Ende damit was berechnet wird. Und wenn ich das Projekt bzw. die Datei beim nächsten Mal öffne, soll natürlich dasselbe Objekt ausgewählt sein. Es soll denselben Zustand habe, wie beim Speichern. So kann man es kurz beschreiben.

02.04.2019 - 21:32 Uhr

Wieso das? Ich habe UI und ein daran gebundenes ViewModel, indem die eingegeben Daten stehen. Diese würde ich gern als Datei speichern. Was ist daran nicht MVVM?

02.04.2019 - 21:13 Uhr

Ich gebe zu, dass ich mich da wohl noch mehr einlesen muss. Eine Frage hätte ich noch. Worin bestet jetzt das Problem? Im der Speicherung der Daten im Xml-Format als serialisiertes Objekt oder darin, wie man aus den eingegebenen Daten im ViewModel eine Datei erzeugt und später aus dieser Datei alles wieder rekonstruiert?

02.04.2019 - 20:21 Uhr

Ich speichere alle eingegebenen Daten, indem ich das oberste ViewModell serialisiere (Xml) und es dann bei Bedarf wieder lade. Wie kann ich das denn besser machen?

02.04.2019 - 17:47 Uhr

Doch ich muss Equals überschreiben, da ich die Objekte in einem Projekt speichere (Serialisiere) und später wieder herstelle, dann funktioniert der Vergleich der Referenzen nicht mehr.

02.04.2019 - 15:04 Uhr

Hallo Taipi,

"Generate overrides" findes du bei "Quick Actions and Refractorings". Visual Studio generiert das dann genauso, wie oben beschrieben. In der MSDN stand beim Pattern für override Equals, dass man auch GetHashCode überschreiben soll. Macht man das nicht, wirft Visual Studio auch eine entsprechende Warnung. Das mit dem Hash, der sich nicht ändern soll, habe ich auch gelesen, das passt ja dann nicht mehr. Etwas wiedersprüchlich das Ganze.

02.04.2019 - 14:39 Uhr

Hallo Abt,

danke für deine Antwort.

Visual Studio Auto Generate liefert das:


public override int GetHashCode()
{
    return 539060726 + EqualityComparer<string>.Default.GetHashCode(Name);
}

base ist Quatsch, da hast du Recht.


+ EqualityComparer<string>.Default.GetHashCode(Name);

verursacht mein Problem. Bliebe noch


public override int GetHashCode()
{
    return 539060726;
}


???

02.04.2019 - 14:07 Uhr

Ich habe die Ursache gefunden.

Wenn ich statt


public override int GetHashCode()
{
    return 539060726 + EqualityComparer<string>.Default.GetHashCode(Name);
}

dies hier


public override int GetHashCode()
{
    return base.GetHashCode();
}

verwende, taucht das Problem nicht auf. Wenn ich das richtig recherchiert habe, wird Equals nicht aufgerufen, wenn GetHashCode() schon unterschiedliche Werte liefert. Meine Frage wäre noch: Ist es legitim, das so zu implementieren, wenn es das macht, was es soll oder gibt es eine sauberere Lösung?

Grüße, Alex

02.04.2019 - 12:22 Uhr

Hallo

mit folgendem Problem komme ich nicht weiter:

Ich habe ein UserControl über TemplateBinding an ein ViewModel gebunden. In diesem VM gibt es eine ObservableCollection<ClasseA> als ItemsSource für ein DataGrid im UserControl mit ClassA wie folgt und einem TextColumn für "Name".


public class ClassA
{
    private string _Name;
    public string Name
    {
        get{ return _Name; }
        set
        {
            if(_Name != value)
            {
                _Name = value;
                OnPropertyChanged("Name");
            }
        }
    }

    //... weitere, hier nicht relevante Properties 


    //Auschnitt von override Equals, GetHashCode und Operatoren
    public override bool Equals(object obj)
    {
        return Equals(obj as ClassA);
    }

    public bool Equals(ClassA other)
    {
        return other != null &&
               Name == other.Name;
    }
}

Mein Problem besteht darin, dass, wenn ich im DataGrid im TextColumn den Namen ändere, ich danach keine anderes Item mehr anwählen kann, bzw. dies dann nicht in die an SelectedItem gebundene Property weitergereicht wird. Ich hab schon rausgefunden, dass das irgendwie mit dem override Equals zusammen hängt, weiß aber nicht, wie ich das Problem beheben kann. Wenn ich das gesamte UserControl über das TemplateBinding neu aufrufe (anderes UC und dann wieder dieses), geht alles wieder und auch die Namensänderung ist übernommen.

Grüße, Alex

16.08.2018 - 12:07 Uhr

Hallo Mr Sparkle,

das Problem ist wie folgt. Ich habe am Rechner ein Gerät, dessen Datum man verstellen kann, aber nicht beliebig. Wenn man nun versucht, ein ungültiges Datum zu setzten, gibt es ein NOK zurück und darauf hin soll die Textbox, die das Gerätedatum anzeigt, kurz blinken. Hat also nichts mit Validierung im Sinne von WPF und MVVM zu tun.

16.08.2018 - 10:55 Uhr

Hallo,

ich habe in meiner Anwendung eine Textbox, deren Text-Property an eine Variable des VM gebunden ist. Nun möchte ich durch ein kurzes Blinken der Textbox den Empfang eines ungültigen Wertes für diese Variable signalisieren.
Die Variable wird dabei nicht geändert, weshalb Eventtrigger mit RoutedEvent=TargetUpdated wohl ausscheidet. Kann ich den Eventtrigger auch über eine weitere Variable des VM auslösen? Wenn ja, wie?

Grüße, Alex

21.06.2018 - 12:59 Uhr

Hallo Sparkle,

auch wenn das etwas philosphisch klingt, aber es kommt darauf an wie man's betrachtet. Im Prinzip ist es egal woher das Objekt deserialisiert wurde. Aber ich muss wissen, wohin mit den erzeugten Daten und deren Speicherort ist der Ordner der xml-Datei. Ich weiß gerade nicht, wie ich das anders lösen soll.

21.06.2018 - 11:13 Uhr

Hallo gfoidl,

vielen Dank für deine Antwort. Zur Thematik FileStream. Es ist sichergestellt, dass das Ojekt immer aus einer Datei serialisiert wird. Hintergrund des Ganzen ist folgender:

Es existiert ein Hauptordner in dem sich mehrere (viele) Unterordner befinden. In jedem dieser Ordner liegt eine zu deserialisierende Datei. Wenn ich in der Anwendung dem deserialisiertem Objekt zugehörige Daten erzeuge (Messwerte, Dokumente usw.), dann sollen die auch in dem entsprechenden Unterordner landen. Deshalb möchte ich den Quellordner (momentan als FileInfo) im Objekt haben.

Grüße, Alex

20.06.2018 - 17:05 Uhr

Hallo,

ich möchte beim Deserializieren eines Objektes den Pfad der Quelldatei als readonly Property mit im Objekt speichern. Da ja beim XML-Deserialisieren der parameterlose Konstruktor verwendet wird, weiß ich nicht so recht, wie ich das anstellen soll. Gibt es da einen offiziellen Weg? Eine Write-Only-Once-Property mit Flag und Exception finde ich nicht so glücklich.

Grüße, Alex

03.01.2018 - 15:28 Uhr

Ich möchte mich ja nicht automatisch verbinden. Ich möchte nur eine Message, wenn ein Gerät sich verbunden hat. Wenn PC <-> Gerät sich kennen (gepaired sind) sollte das doch automatisch gehen, wenn sie in Reichweite sind. Und wenn das passiert bzw. wenn manuell eine Verbindung hergestellt wurde, hätte ich gern eine Message/Event, damit die Software bescheit weiß.

03.01.2018 - 14:24 Uhr

32feet habe ich natürlich gefunden, das unterstützt aber den BT-Stack meines Adapters nicht. Ich hab inzwischen noch bisschen weiter recherchiert und fürchte, dass das nicht ganz so trivial ist wie oben mit USB, weil man offensichtlich eine Verbindung zum BT-Adapter herstellen muss. Eine generelle Variante scheint also schwierig, was doof ist, da ich ja nicht weiß, auf welchem Rechner die Anwendung später läuft.

Vielleicht sollte ich noch erwähnen, dass ich am Ende mit SPP bzw. COM-Port kommunieren möchte. Ich möchte nur die Ports scannen, wenn eines meiner Geräte sich mit dem Rechner verbindet, damit man das nicht immer manuell machen muss. In der eigentlichen Anwendung habe ich mit der eigentlichen Bluetooth-Kommunikation gar nichts zu tun.

03.01.2018 - 13:43 Uhr

Hallo,

ich versuche gerade, meine Software dazu zu bringen, dass sie mich benachrichtigt, wenn ein Bluetooth-Gerät mit dem Rechner verbunden oder die Verbindung getrennt wird.

Für USB-Geräte habe ich das schon mal wie folgt implementiert:


private void Window_SourceInitialized(object sender, EventArgs e)
{
    //hook in to receive device changed event 

     IntPtr windowHandle = (new WindowInteropHelper(this)).Handle;
     HwndSource src = HwndSource.FromHwnd(windowHandle);
     src.AddHook(new HwndSourceHook(WndProc));
}

private IntPtr WndProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) //device added or removed
{
    // address the messages you are receiving using msg, wParam, lParam
    if (msg == 537) //WM_DEVICECHANGE
    {
        if ((int)wParam == 7) //DBT_DEVNODES_CHANGED
            _PortScanner.StartScan();
     }

     return IntPtr.Zero;
}

Nun möchte ich das Ganze, wie gesagt, für Bluetooth haben. Google hat das hier gefunden:

Bluetooth Programming with Windows Sockets

Bluetooth and WM_DEVICECHANGE Messages

Aber so richtig schlau werde ich daraus nicht und bräuchte etwas Hilfe.

Grüße, Alex

17.11.2017 - 09:54 Uhr

Update:

ausgehend von Sir Rufos Post habe ich noch etwas rumprobiert und herausgefunden, dass im ViewModel-Konstruktor tatsächlich


SynchronizationContext.Current == null;

Ausgehend von diesem Post

Of course there is no SynchronizationContext available when the entry point (Main) of your application is hit. You need to wait for the framework to initialize it.

In a Windows Forms application this happens when the first form is created. So only after the Application.Run method has been called, the SynchronizationContext.Current property will actually return a synchronization context.

habe ich festgestellt, dass der ViewModel-Konstruktor vor der App.OnStartup ausgeführt wird. In meinem anderen Projekt, wo es funktionierte, ist das nicht so. Als erste Lösung habe ich


 _ProgressIndicator = new Progress<CommunicationResult>(param => ReportProgress(param));

in die Kommando-Methode verlegt. Und siehe da, es geht.

Danke und Grüße, Alex

17.11.2017 - 08:37 Uhr

Ich poste mal den grundsätzlichen Code. Der oben stehende Code befindet sich im ViewModel.

Dann habe ich noch eine Klasse Bootloader, die hat einige asynchrone Methoden zur Gerätekommunikation.

Auf Knopdruck gehts los (Command)


private async void UpdateDevice(object param)
{
    UpdateStringList.Clear();
    Success = true;

    IntelHexFile file;
            
    if (IntelHexFile.TryParse(HexFileName, out file))
         await _Bootloader.UpdateDevice(Port, file, EraseEEPROM, _ProgressIndicator);
}

Öffentliche Methode der Bootloaderklasse


public async Task<bool> UpdateDevice(string portName, IntelHexFile file, bool eraseEEPROM, IProgress<CommunicationResult> progressIndicator)
{
    IsBusy = true;

    if (progressIndicator == null) return false;

    BlockList blockList = CreateBlockList(file);

    BlockList.State state = BlockList.Validate(blockList);

    bool success = state == BlockList.State.Valid;

//schnipp

//schnapp
     
    success = await SearchDevice();

    if (!success)
    {
        progressIndicator.Report(new CommunicationResult(true, 100, "Bitte Gerät einschalten", true));
        success = await WaitForDevice(5);
    
        if (!success)
            progressIndicator.Report(new CommunicationResult(false, 100, "kein bootbares Gerät an Port: " + portName + " gefunden", false));
        else
            progressIndicator.Report(new CommunicationResult(true, 100, "Gerät an Port: " + portName + " gefunden", false));
                }
        else
            progressIndicator.Report(new CommunicationResult(true, 100, "Gerät an Port: " + portName + " gefunden", false));
     }

     if (success)
     {
          progressIndicator.Report(new CommunicationResult(true, 0, "Signatur lesen... ", false));

          success = await CheckSignature(new byte[] { 0x4C, 0x95, 0x1E });

          if (!success)
               progressIndicator.Report(new CommunicationResult(false, 100, "nicht OK", true));
          else
          {
//schnipp

So sieht das grob aus. es gibt eine öffentliche Methode, die aufgerufen wird und nicht öffentliche Methoden in dieser, die dann die einzelnen Schritte ausführen. Dazwischen wird das Ergebnis eines Teilschrittes zurückgemeldet.

Hier mal noch eine der Methoden


private async Task<bool> EraseDevice(bool eraseEEPROM)
{
    return await Task.Run(() =>
    {
        try
        {
            _Port.Write("e");
            if (eraseEEPROM)
               _Port.Write("1");
            else
                _Port.Write("0");
            Task.Delay(1000).Wait();    //give it a little extra time to erase the memory
            _Port.ReadLine();   //newline character expected, 1s time out
            return true;
        }
        catch (Exception) { return false; }
    });
}

Grüße, Alex

16.11.2017 - 23:13 Uhr

Wie findet man das heraus? Der ViewModel-Konstruktor wird im UI-Thread aufgerufen. Ich muss gestehen, dass mir der Begriff SynchronisationsContext neu ist.

16.11.2017 - 17:11 Uhr

Ich hab nochmal gegoogled und das hier gefunden:

The Progress<T> constructor captures the current SynchronizationContext object.

The SynchronizationContext class is a facility that abstracts the particulars of the involved threading model. That is, in Windows Forms it will use Control.Invoke, in WPF it will use Dispatcher.Invoke, etc.

When the progress.Report object is called, the Progress object itself knows that it should run its delegate using the captured SynchronizationContext.

In other terms, it works because Progress has been designed to handle that without the developer having to explicitly say it.

Was ja genau heißt, dass ein Invoke nicht erforderlich ist, oder verstehe ich das falsch?

Grüße, Alex

16.11.2017 - 16:46 Uhr

Message ist:

Fehlermeldung:
Von diesem CollectionView-Typ werden keine Änderungen der "SourceCollection" unterstützt, wenn diese nicht von einem Dispatcher-Thread aus erfolgen.

Okay, das erklärt zumindest, warum der ProgressBar funktioniert. Allerdings habe ich das alles schon mal genau so in einem anderen Projekt implementiert und da hatte ich das Problem nicht.

Grüße, Alex

16.11.2017 - 16:21 Uhr

Hallo inflames2k,

sorry, vergessen zu erwähnen:


private readonly ObservableCollection<ProgressItem> _UpdateStringList;
public ObservableCollection<ProgressItem> UpdateStringList
{
    get { return _UpdateStringList; }
}

Grüße, Alex

16.11.2017 - 16:07 Uhr

Hallo,

ich habe für ein Gerät einen Bootloader geschrieben. Zu diesem entwickle ich gerade Anwendung. Da einzelne Vorgänge länger dauern, habe ich diese in asynchrone Methoden ausgelagert und per IProgress update ich die UI, damit der Benutzer sieht, dass noch etwas passiert.

Ich habe in meinem ViewModel einen


private readonly Progress<CommunicationResult> _ProgressIndicator;

Im Konstruktor:


_ProgressIndicator = new Progress<CommunicationResult>(param => ReportProgress(param));

sowie eine Methode


private void ReportProgress(CommunicationResult progress)
{
     if (!progress.Success)
     Success = progress.Success;
     ProgressState = progress.Progress;
     ProgressItem item = new ProgressItem(progress.Message, progress.IsImportant);
     UpdateStringList.Add(item);
}

ProgressState und UpdateStringList sind gebunden an die View (ProgressBar und ItemsControl). Wenn ich ProgressState ändere ist alles prima und der ProgressBar ändert seinen Wert. Bei UpdateStringList.Add... bekomme ich die Exception. Wenn ich alles in ein Invoke packe geht's. Ich dachte der Progress übernimmt den Kontext von dort, wo erstellt wird. Und warum kommt die Exception nicht schon beim Ändern von ProgressState, der ja auch an die UI gebunden ist?

Grüße, Alex

20.10.2017 - 14:55 Uhr

Kurzes Feedback:

ich habe in meiner Kommunikationsklasse ein Callback Action<T> implementiert, das nach jeder Kommunikation aufgerufen wird. Im MainViewModel gibt es dann eine Callbackfunktion die ja nach Typ der beantworteten Kommunikation die entsprechende Aktion ausführt.

Danke für die Hinweise und Tipps.

Grüße, und schönes Wochende,

Alex

20.10.2017 - 09:26 Uhr

Hallo,

ich arbeite gerade an einer Software, die per SerialPort mit einem externen Gerät kommuniziert. Da die Antwort des Geräts manchmal etwas dauert, möchte ich das ganze aus dem GUI-Thread auslagern. Weiterhin kann die Kommunikation von verschiedenen Stellen im Programm erfolgen. Damit es keine Kollisionen gibt habe ich eine Klasse geschrieben die je eine ConcurrentQueue für Kommunikationsanfragen und Antworten enthält sowie einen Thread, der die Anfragen aus der einen Queue holt, die Kommunikation durchführt und die Antworten in die andere Queue packt.

Meine Frage ist, wie bekomme ich auf MVVM-verträgliche Art die Antwort zurück zum Fragesteller (Event oder ein anderes Messaging), bzw. hat jemand eine grundsätzlich bessere Lösung für das ganze?

Grüße, Alex

30.06.2017 - 11:38 Uhr

Hallo,

ich habe eine

ObservableCollection<myClass> 

mit Objekten, die selbst auch wieder als eine Property eine

ObservableCollection<uint>

enthalten. Nun möchte ich mittels CompositeCollection diese ObservableCollections, deren Anzahl ja variieren kann, an die ItemsSource einer ComboBox binden, sodass alle uint in der Box erscheinen.


<CompositeCollection>
    <CollectionContainer Collection="{Binding Path=Element[0]"/>
    <CollectionContainer Collection="{Binding Path=Element[1]"/>

<!-- weitere Collections unbekannter Anzahl -->

</CompositeCollection>

Geht das überhaupt, und wenn ja, wie?

Grüße, Alex

09.12.2016 - 09:29 Uhr

Hallo Abt,

ich wollte mich nochmal wegen der Problematik an dich wenden. Ist es das in diesem Thread beschriebende Vorgehen, das Du meinst?

Have default string resource file and override it with custom ones

08.12.2016 - 15:32 Uhr

Jetzt überforderst Du mich ein bisschen, was daran liegt, dass ich mich mit dieser Problematik noch nie auseiandergesetzt habe. Vielleicht kannst Du mir ein paar Stichwort oder Links nenne, damit ich in dieses Thema reinkomme.

Die Problematik ist auch die, dass ich im Augenblick nur Dummy-Texte hab. Die Anwendung soll unter anderem ein Protokoll erstellen, in dem dann bei Fehler XY ein Text steht ala: "Das und das ist kaputt". Den Wortlaut lege aber nicht ich fest. Und um das ganze etwas flexibel zu gestalten, habe ich das in einer editierbare XML gepackt. Wenn es dafür professionellere Vorgehensweise gibt, lasse ich mich gern belehren.

08.12.2016 - 15:13 Uhr

Der Benutzer soll die Texte gegebenenfalls ändern können.

08.12.2016 - 13:55 Uhr

Ja, die XML wird bei Programmstart deserialisiert und stellt bestimmte Texte bereit, die in der Anwendung angezeigt werden.

08.12.2016 - 13:30 Uhr

Hallo,

ich habe folgende Frage:

Ich möchte bei einer ClickOnce Installation eine xml-Datei, welche die Anwendung zu Initialisierung benötigt, in ein festgelegtes Verzeichnis kopieren, z.B "Users\Name\AppData\Local\Anwendungsname". Kann ich mein Projekt-Setup derart gestallten, dass das bei der Installation automatisch geschieht, oder muss ich das aus der Anwendung heraus manuell machen?

Grüße, Alex

29.11.2016 - 17:46 Uhr

Hallo P!lle,

danke für dein Mühe. Funktioniert prima.

Grüße, Alex

28.11.2016 - 12:04 Uhr

Ich möchte eigentlich mit Hilfe des Headers der GroupBox zeigen, dass sich einer der Werte geändert hat, als Eye-Catcher sozusagen. Das ist auch nicht meine Idee, ich darf das nur umsetzten. Ich dachte ich "fange" irgendwie das TagredUpdated der unterliegenden TextBoxen mit einem EventTrigger aus, aber das bekomme ich gerade nicht hin.

28.11.2016 - 10:22 Uhr

Hallo,

mit folgendem Problem komme ich nicht weiter:

Ich habe eine GroupBox, in der sich TextBoxen befinden, welche im ViewModel an Properties gebunden sind. Nun möchte ich, dass der GroupBox-Header animiert wird, wenn sich einer der TextBox-Werte im VM ändert.

Dazu habe ich in den TextBoxen beim Binding "NotifyOnTargetUpdate" auf true gesetzt. Nun weiß ich nicht genau mit welchem Trigger ich im GroupBox-Header die Animation auslösen soll. Ich hab noch was von Binding.SourceUpdated="OnBindingSourceUpdated" gelesen in einem anderen Forum, bringe das ganze aber nicht so recht zusammen.

GroupBox-Header sieht etwa so aus:


<GroupBox.Header>
                    <TextBlock Height="16" Text="Messwerte" TextAlignment="Center" VerticalAlignment="Center">
                        <TextBlock.Triggers>
                            <Trigger Binding.SourceUpdated="OnBindingSourceUpdated">
                                <Trigger.EnterActions>
                                    <BeginStoryboard>
                                        <Storyboard>
                                            <ColorAnimation Storyboard.TargetProperty="Foreground.Color" AutoReverse="False" BeginTime="0:0:0" Duration="0:0:0.1" To="Red"/>
                                            <DoubleAnimation Storyboard.TargetProperty="FontSize" AutoReverse="False" BeginTime="0:0:0.2" Duration="0:0:0.4" To="14"/>
                                            <DoubleAnimation Storyboard.TargetProperty="FontSize" AutoReverse="False" BeginTime="0:0:0.5" Duration="0:0:0.7" To="12"/>
                                            <ColorAnimation Storyboard.TargetProperty="Foreground.Color" AutoReverse="False" BeginTime="0:0:0.8" Duration="0:0:0.1" To="Black"/>
                                        </Storyboard>
                                    </BeginStoryboard>
                                </Trigger.EnterActions>
                            </Trigger>
                        </TextBlock.Triggers>
                    </TextBlock>
                </GroupBox.Header>

Der Trigger stimmt offensichtlich nicht.

Grüße, Alex

13.09.2016 - 14:44 Uhr

Danke. Ich schau mir das mal an. Hatte kürzlich erst hier im Forum einen Link auf einen TaskDialog gefunden und bin gerade dabei mir was abgespecktes zu basteln. Vielleicht kann ich mir das ja nun sparen.

Grüße, Alex

12.09.2016 - 01:24 Uhr

Es handelt sich um ObservableCollection<CustomClasses> aus einem ViewModel. Hat also eigentlich nichts mit Dateien zu tun. Theoretisch würde eine MessageBox ausreichen, ich benötige aber noch die CheckBox für "Einscheidung für alle folgenden beibehalten"

Grüße, Alex

09.09.2016 - 22:32 Uhr

Hallo, danke für den Link. Aber wenn ich mir das so durchlese, scheint das nur beim Kopieren von Dateien zu gehen. Ich würde den Dailog jedoch gern manuell aufrufen, da ich ja keine Dateien, sondern Datensätze kopiere. Also wie eine Messagebox zum Beispiel.

Grüße, Alex

09.09.2016 - 16:34 Uhr

Hallo,

ich möchte in einem Projekt zwei Listen von Datensätzen zusammenführen. Wenn in diesen Listen doppelte Datensätze existieren, möchte ich einen Dialog anzeigen, ähnlich wie beim verschieben von Dateien in Windows, der die Möglichkeiten: "ja", "nein" und "Entscheidung für alle weiteren merken" bietet. Muss ich den selber bauen oder kann ich den Windows-eigenen Dialog verwenden. Wie rufe ich den auf?

Grüße, Alex

09.09.2016 - 10:33 Uhr

Im Moment noch TemplateColumn mit ComboBox als EditingTemplate und TextBox im CellTemplate. Die Lösung mit dem Proxy werde ich bei Gelegenheit mal testen. Witzigerweise habe ich im selben Dokument schon sowas, aber mit anderem Datenkontext. Ich bräuchte also einen zweiten. Ich teste das mal. Bzw. wie würdest du es denn machen?

08.09.2016 - 17:07 Uhr

Binding-Fehler hatte ich natürlich, konnte sie mir aber nicht erklären. Den Trick mit dem Binding-Proxy kenne ich, das Problem mit VisualTree, DataGrid und DataGridColumn ist mir allerdings nicht bekannt gewesen. Danke für die Antwort.

Grüße, Alex