Laden...
xxxprod
myCSharp.de - Experte
36
Themen
1.378
Beiträge
Letzte Aktivität
vor 2 Jahren
Dabei seit
13.04.2006
Alter
43
Beruf
Programmierer
Herkunft
Österreich\Wien
Erstellt vor 4 Jahren

Mmmh, die Idee war eigentlich, dass automatisch nach der Sensorhardware gesucht wird und nix eingestellt werden muss. Im Fall der o.g. seriellen Ports eine feste Baudrate, etc. und im Falle eines Wechsel auf direkte USB-Kommunikation gibt's wahrscheinlich auch nix einzustellen.

Ich hab mich dabei auf dein Kommentar bezogen:

Von der GUI zur Logikschicht, also bspw. für die Einstellungen der Sensoren, hier bin ich unschlüssig, wie das aussehen soll

Ich hab eine eigene Klasse für den COM-Port definiert. Hier gibt's ein privates Serialport-Objekt, welches bei Instanzierung nach der Hardware sucht. Öffentlich mache ich nur die o.g. Funktionen über das Interface. Meinst du das mit auslagern und kapseln?

Jap genau das meinte ich... nur nochmals wiederholt um die Wichtigkeit hervorzuheben 😃

Das hatte ich vergessen zu erwähnen, ich bin "klassisch" mit WinForms unterwegs. Ich sehe keine Vorzüge in WPF (wobei ich mich mit tieferen Infos dazu auch nicht weiter beschäftigt habe). Da VS wohl keinen Editor dafür hat und man dafür auch noch XML(?) an der Backe hat, um die GUI zu definieren, war das für mich nicht interessant.

Ich habe auch mit WinForms angefangen und sehe seit WPF keinen Grund mehr das Zeugs jemals wieder anzugreifen 😃
Es ist sicherlich eine Umstellung aber man arbeitet sich glaub ich da schnell ein da es mMn. wesentlich intuitiver ist als WinForms.

Ein Qualitätskriterium für mich ist wie testbar Code ist (weswegen ich ständig vom Testen rede) - ich arbeite nicht immer (eher selten) nach TDD-Regeln aber zumindest schau ich dass ich alles soweit entkopple, dass jeder entscheidende Code-Pfad ohne Nebeneffekte getestet werden kann. Das begingt wie schon mehrmals erwähnt beim Auslagern von Code in eigene Klassen, weiter noch die Abhängigkeiten der Klassen untereinander durch Interfaces definieren, sodass am Ende jede Klasse beispielsweise nur mit "Fake-Instanzen" getestet werden kann.

Erstellt vor 4 Jahren

Hallo Locutus,

das ist schon mal ein guter Ansatz den du da vorgeschlagen hast und einiges bei der Implementierung ist mMn. wirklich Geschmackssache und solche Vorgehensmodelle sollen dabei helfen die Komplexität zu reduzieren sowie Test- und Wartbarkeit verbessern.

Ich würde auch so Anfangen die externen Resourcen zu kapseln. Die verschiedenen Hardware-Schnittstellen zB. durch ein gemeinsames Interface kann für gewisse Consumer im Code Sinn machen um einheitlich mit den Schnittstellen zu kommunizieren aber speziell die Konfiguration der unterschiedlichen Hardware-Schnittstellen wird sich mit einem allgemeinem Interace nicht abbilden lassen und somit wird man vermutlich Richtung GUI konkretere Interfaces pro Hardware-Schnittstelle brauchen.

Mal abgesehen von den Interfaces die man dafür definiert, der Zugriff sollte ausgelagert und gekapselt sein, was das Testen dieser Schnittstellen erst ermöglicht.

Eine Logik-Klasse kann wahlweise entweder alle Schnittstellen kennen und bedienen oder noch einmal separat pro Schnittstelle existieren - und vlt. noch eine Logik-Klasse darüber haben die diese wieder vereint... Auch wieder aus dem selben Aspekt der Test-und Wartbarkeit. Wenn die Logik sich pro Hardware-Schnittstelle gravierend unterscheidet würd ich teilen, ansonsten reichts wsl. in einer.

Die Logic-Klasse kann wie du vorgeschlagen hast per Calls und Events mit den Hardware-Schnittstellen-Klassen kommunizieren und selbst seine Zugriffe auch wieder durch Funktionen und Events öffentlich machen.

Richtung GUI (angenommen du verwendest WPF) hast du dann ein ViewModel pro View die du darstellen willst, welche die notwendigen Properties (für die View) im Sinne von MVVM an die Gui-Elemente bindet. Die ViewModels sind dann für die Interaktion mit den Logics verantwortlich.

Dein Beispiel mit GetPorts(): Das ViewModel ruft zB. bei der Initialisierung (oder auf Abruf per ICommand von der View getriggert) die Funktion der Logic.GetPorts() auf und setzt das Result einem "Port[] Ports{get;set;}" Property, welches durch INotifyPropertyChanged die GUI benachrichtig, dass diese sich aktualisieren und neue Werte darstellen soll.
Das ViewModel hat quasi die Aufgabe, die Logics für die View besser konsumierbar zu machen.

Auch in den Views und ViewModels: Wenn du die Hardware-Schnittstellen per View Konfigurieren willst, brauchst du wsl. spezifische Views pro Hardware-Schnittstelle (da wsl. unterschiedliche Parameter konfiguriert werden) und dazu spezifische ViewModels, welche diese dann den Logics order Hardware-Schnittstellen-Klassen weiterleiten können.

Also zusammengefasst schaut dein Ansatz unterhalb der GUI schon ordentlich aus und Richtung GUI schau dir [Artikel] MVVM und DataBinding an und auch den WPF Example Code von OxyPlot an.

Da du durch das Auslagern des Codes in verschiedene Komponenten wsl. viele Klassen inkl. Interfaces erzeugen wirst empfiehlt sich Dependency Injection einzusetzen um die Abhängigkeiten zu reduzieren, das Kompositionieren der Services zu vereinfachen und vor allem um den Code testbarer zu machen.

LG, XXX

Erstellt vor 4 Jahren

Hallo Mattes80,

DataContext kann nur ein Objekt zugewiesen werden. Normalerweise hat das Fenster ein MainViewModel, und die einzelnen Unterbereiche im Fenster dann spezielle Unter-ViewModels, welche als Eigenschaften im MainViewModel liegen. Das kann beliebig verschachtelt werden.

Nach dem Schema würde ich auch vorgehen und du könntest es dann zB so schachteln:

MainViewModel
-> SprachViewModel
-> DatenbankViewModel
-> FunktionsViewModel

Die Struktur kannst du auch in Form von verschachtelten Views wiederspiegeln und zB eine ähnliche Struktur in den Views anlegen:

MainView
-> SprachView
-> DatenbankView
-> FunktionsView

Das Hauptfenster bekommt als DataContext dann das MainViewModel und alles weitere ergibt sich rein aus den Bindings:


<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">

    <Window.DataContext>
        <local:MainViewModel></local:MainViewModel>
    </Window.DataContext>

	<Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>

        <local:SprachView Grid.Column="0" DataContext="{Binding Path=SprachViewModel}"></local:SprachView>
        <local:DatenbankView Grid.Column="1" DataContext="{Binding Path=DatenbankViewModel}"></local:DatenbankView>
        <local:FunktionsView Grid.Column="2" DataContext="{Binding Path=FunktionsViewModel}"></local:FunktionsView>

	</Grid>
</Window>

<UserControl x:Class="WpfApp1.SprachView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:wpfApp1="clr-namespace:WpfApp1"
             mc:Ignorable="d"
             d:DesignHeight="450" d:DesignWidth="800" 
             d:DataContext="{d:DesignInstance wpfApp1:SprachViewModel}">
	<Grid>
		<ListView ItemsSource="{Binding Sprachen}" />
	</Grid>
</UserControl>

und die entsprechenden ViewModels stark vereinfacht:


	public class MainViewModel
	{
		public SprachViewModel SprachViewModel { get; set; } = new SprachViewModel();
		public DatenbankViewModel DatenbankViewModel { get; set; } = new DatenbankViewModel();
		public FunktionsViewModel FunktionsViewModel { get; set; } = new FunktionsViewModel();
	}

	public class SprachViewModel
	{
		public List<string> Sprachen { get; set; } = new List<string> {"Deutsch", "Englisch"};
	}

	public class DatenbankViewModel
	{
		public List<string> Datenbanken { get; set; } = new List<string> {"DbA", "DbB"};
	}

	public class FunktionsViewModel
	{
		public List<string> Funktionen { get; set; } = new List<string> {"DoSomething", "DoSomethingElse"};
	}

Lg, XXX

Erstellt vor 9 Jahren

Ich hab die Fragen auch unglücklich formuliert gefunden. Danke jedenfalls für das Feedback - das wird ihm hoffentlich auch weiterhelfen. 😃

Erstellt vor 9 Jahren

Hallo,

ein Kollege in der FH hat im Rahmen seiner Bac-Arbeit eine Umfrage gestartet und gebeten, diese auch an andere weiterzuleiten. Sind 21 Fragen die vielleicht etwas klarer formuliert sein könnten aber trotzdem wärs nett, wenn sich der eine oder andere dafür opfert: Hier gehts zur Umfrage

Danke,
XXX

Erstellt vor 9 Jahren

Ich kanns nicht erklären warum "Path=." den Wert nicht mehr zurückschreibt aber es ist nunmal so: Man kann nur die Eigenschaften des Context verändern, nicht aber den Context selbst.

Hier ein Beispiel zum Veranschaulichen:

<Window x:Class="WpfApplication2.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 Orientation="Vertical">

      <TextBox Text="{Binding TextProp1, UpdateSourceTrigger=PropertyChanged}"></TextBox>
      <TextBox DataContext="{Binding TextProp2, UpdateSourceTrigger=PropertyChanged}"
               Text="{Binding Path=., UpdateSourceTrigger=PropertyChanged}"></TextBox>

   </StackPanel>
</Window>


   public partial class MainWindow : Window
   {
      private string _textProp1;
      private string _textProp2;

      public MainWindow()
      {
         InitializeComponent();

         DataContext = this;

         TextProp1 = "Text1";
         TextProp2 = "Text2";
      }

      public string TextProp1
      {
         get { return _textProp1; }
         set { _textProp1 = value; }
      }

      public string TextProp2
      {
         get { return _textProp2; }
         set { _textProp2 = value; }
      }
   }

TextBox1.Text ist an DataContext.TextProp1 gebunden
TextBox2.Text ist an DataContext gebunden, welcher selbst auf DataContext.TextProp2 geändert wurde.

Wenn du nun einen Breakpoint bei beiden Settern setzt, siehst du das (1) verändert wird aber (2) nicht.

Lg, XXX

//Edit: Um meinen vorigen Vorschlag nochmal zu verdeutlichen: Deine Items in der Listbox müssen in einem Wrapper-Objekt sein, damit du eine Property hast die du verändern kannst. Du kannst nicht den Kontext selbst ändern aber die Eigenschaften sehrwohl.

Erstellt vor 9 Jahren

Hallo Palin,

wie hast du denn das SQL der Statements extrahiert? Per SQL-Profiler? Falls nicht würde ich das nochmal probieren: Die komplette Abfrage (nicht nur die einzelnen separiert) im Profiler loggen lassen und dann gemeinsam im SSMS ausführen lassen um zu sehen obs dort funktioniert.

Weiters kann es sein (und hatte ich schonmal), dass Sachen im SSMS funktionieren, die aber im PGM nicht funktionierten. Ich kann mich nur mehr grob daran erinnern, dass "SET ARITHABORT OFF/ON" da teilweise geholfen hat bzw. kann es auch Probleme mit dem Ausführungsplänen im SQL Server geben. Evt. mal die irgendwo resetten probieren.

Wie schauts aus, wenn du das Timeout anhebst? Wird die anfrage dann fertig oder nicht?

Lg, XXX

Erstellt vor 9 Jahren

Also um es zum Verständnis zu vervollständigen:

  1. Du hast eine ListBox in der die "ausgewählten Produkte" dargestellt werden
  2. Irgendwo (extern) fügst du dann ein neues "Produkt" deiner Liste hinzu, welches vermutlich am Anfang leer sein wird.
  3. Jeder Eintrag in der ListBox wird durch eine ComboBox dargestellt, welche selbst widerum alle Produkte zur Auswahl hat.
  4. Dadurch kann man dann in der Liste der ausgewählten Produkte diese noch verändern, was sich klarerweise auch in der Liste der ausgewählten Produkte widerspiegeln soll.
  5. (später soll neben jedem Item in der Liste noch ein Button zum Entfernen hinzukommen)

Ich vermute mal das das Problem bei der Art des Bindings des SelectedItems zu suchen ist.

  • Mein erster Versuch wäre, die ListBox-Produkte in eine Wrapper-Klasse "ObservableList<SelectedProduct>" zu stecken. SelectedProduct ist in dem Fall ein ViewModel, welches das Binding erleichtern soll und selbst nur ein Property "Product" (inkl. NotifyPropertyChanged) hat.

  • Das Binding auf SelectedItem würde dann nicht auf "Path=." sondern "Path=Product" in SelectedProduct schauen und jede Manipulation würde dann wieder ordentlich in alle Richtungen durchschlagen.

Lg, XXX

Erstellt vor 9 Jahren

In dem Link von mir macht einer einen Vorschlag wie er denkt das es gehen könnte. Eine eigene ComboBox basteln ist aber auch nicht so schlimm...

Vielleicht hilft dir aber auch eine sogenannte "AutoCompleteTextBox" weiter. Dazu gibts ein paar Projekte auf CodePlex zB.

Lg, XXX

Erstellt vor 9 Jahren

Hallo Christel,

  • kommt der Freeze immer zur selben Zeit/bei der selben Aktion?
  • kannst du das Verhalten beim Debuggen auch nachvollziehen?
  • wenn die App gerade eingefroren ist, sieht man dann im TaskManager ungewöhnliche CPU-Last und/oder Festplattennutzung?

Lg, XXX

10 von 1.378 Beiträgen