Wo ist denn das Problem bzw. wo ist das von dir erwartete Verhalten dokumentiert.
Wenn die Validierung fehl schlägt, dann bleibt bei entsprechender Einstellung der Focus auf der TextBox
. Somit können andere Elemente, die den Focus benötigen nicht mehr erreicht werden. EinLabel
gehört aber nicht zu diesen "Ich brauche den Focus" Elementen.
Such mal mit dem Stichwort TreeMap in der Suchmaschine deiner Wahl, da finden sich diverse Anbieter mit so einem Control
Für das reine Anzeigen kannst du PreviewHandler verwenden.
Das Einbetten so eines PreviewHandlers in WPF siehst du in PreviewHost (GeeLaw)
Zitat von Th69
BlonderHans, du hast noch einen kleinen C&P Fehler in
Jo, das kommt davon, wenn man keine Unit-Tests schreibt.
Im Anhang habe ich dir mal ein Beispiel-Projekt gepackt, was deinem recht nahe kommt.
Inklusive Dependency-Injection (Registrierung erfolgt in der Program.cs
) und einen Framework für MVVM (reactiveUI) was das Handling erheblich vereinfacht.
So sehen z.B. die ViewModels aus:
public class MainWindowViewModel : ViewModelBase
{
private readonly Page1ViewModel _page1;
private readonly Page2ViewModel _page2;
public ReactiveCommand<Unit, Unit> Page1Command { get; }
public ReactiveCommand<Unit, Unit> Page2Command { get; }
[Reactive] public PageViewModelBase CurrentPage { get; private set; }
public MainWindowViewModel( Page1ViewModel page1, Page2ViewModel page2 )
{
_page1 = page1;
_page2 = page2;
Page1Command = ReactiveCommand.CreateFromTask( OnPage1 );
Page2Command = ReactiveCommand.CreateFromTask( OnPage2 );
}
private async Task OnPage1()
{
CurrentPage = _page1;
await _page1.InitializeAsync();
}
private async Task OnPage2()
{
CurrentPage = _page2;
await _page1.InitializeAsync();
}
}
sowie
public class Page1ViewModel : PageViewModelBase
{
[Reactive] public string Id { get; set; }
[Reactive] public string Firstname { get; set; }
[Reactive] public string Lastname { get; set; }
}
und die View
<Window x:Class="WpfApp.Views.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:local="clr-namespace:WpfApp.Views"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:viewmodels="clr-namespace:WpfApp.ViewModels"
Title="MainWindow"
Width="800"
Height="450"
d:DataContext="{d:DesignInstance IsDesignTimeCreatable=False,
Type={x:Type viewmodels:MainWindowViewModel}}"
mc:Ignorable="d">
<DockPanel>
<StackPanel DockPanel.Dock="Left">
<Button Command="{Binding Page1Command}"
Content="Page1" />
<Button Command="{Binding Page2Command}"
Content="Page2" />
</StackPanel>
<ContentControl Content="{Binding CurrentPage}">
<ContentControl.Resources>
<DataTemplate DataType="{x:Type viewmodels:Page1ViewModel}">
<GroupBox Background="LightCoral"
Header="Page 1">
<StackPanel>
<DockPanel>
<Label Content="Id:" />
<TextBox Text="{Binding Id, UpdateSourceTrigger=PropertyChanged}" />
</DockPanel>
<DockPanel>
<Label Content="Firstname:" />
<TextBox Text="{Binding Firstname, UpdateSourceTrigger=PropertyChanged}" />
</DockPanel>
<DockPanel>
<Label Content="Lastname:" />
<TextBox Text="{Binding Lastname, UpdateSourceTrigger=PropertyChanged}" />
</DockPanel>
</StackPanel>
</GroupBox>
</DataTemplate>
<DataTemplate DataType="{x:Type viewmodels:Page2ViewModel}">
<local:Page2Control />
</DataTemplate>
</ContentControl.Resources>
</ContentControl>
</DockPanel>
</Window>
Das kannst da als Basis für weitere Experimente verwenden.
Da ist doch mal wesentlich mehr Fleisch dran.
Wenn du jetzt noch verraten könntest WO der ominöse Button
sein soll (im MainWindow
, Page1
oder Page2
) und welche Eigenschaft (also von welcher Klasse und Instanz) damit geändert werden soll, dann wäre das Bild komplett.
Zitat von CSharpNewbie2022
Ich habe [...] und auch die Dependency Injektion und wollte mein Projekt verbessern.
Davon sehe ich hier aber nichts.
Ich versuche mal zu ergründen was du so willst.
Button auf dem Window drücken [...] soll etwas in der page passieren
Eine Möglichkeit ist beschrieben in Befehlsübersicht
Ich habe deinen Code mal nur so überflogen allerdings sehe ich ich fast überall wo ich hinschaue Fehler, das es mir zu viele sind als jetzt auf jeden einzugehen.
Schau dir doch einfach mal in Ruhe die Beispiele an die du genannt bekommen hast und versuche mit denen zu arbeiten und vor allem das Konzept MVVM zu verstehen.
Zitat von tomschrot
- void Reset(): setzt den Index aufs 1. Element
In der Original Beschreibung steht
Sets the enumerator to its initial position, which is before the first element in the collection.
Der Index steht also nach Reset()
vor dem ersten Element und nicht darauf.
Wenn du dein Problem etwas eleganter beschreiben könntest, könnte man dir bestimmt helfen.
z.B. Ein Window (auf deutsch Fenster) besteht aus 4 Fenstern … ah, ja
Ich kann mir nicht vorstellen, was du wirklich haben möchtest.
Schau dir System.Windows.Application.SessionEnding an
Wenn du weiter Kopfschmerzen haben möchtest, dann mach mit diesem IndexOf
weiter.
Wenn du es einfach lösen möchtest, dann verwendest du z.B. folgendes
var doc = new XmlDocument();
doc.Load( "WieAuchImmerDieHeisst.emp" );
var elements = doc.GetElementsByTagName( "S114x1894" )
.OfType<XmlElement>()
.Where( e => e.Attributes is not null && e.Attributes.OfType<XmlAttribute>().Any( a => a.Name == "A2011" && a.Value == "XXXValueSet1YYY" ) )
.ToList();
In elements
findest du jetzt alle betroffenen Elemente und kannst diese jetzt ganz gemütlich ändern.
Am Ende speicherst du den ganzen Kladderadatsch wieder ab mit doc.Save( "WieAuchImmerDieHeisstBearbeitet.emp" );
Du kannst dir auch XPath anschauen
<root>
<S114x1894 A2011="SMT-10M-PS-24V-E-0,3-L-M8D / 551375 / C-Nut" A2012="FES.551375;IEC_symbol\;1\;146\;6;;FES.551375;IEC_symbol\;1\;146\;6;MURR.7000-41211-0000000;MURR.7000-12221-6341000;Artikelnummer;;1;1"/>
<S114x1894 A2011="SMT-8M-A-PS-24V-E-0,3-M8D / 574334 / T-Nut" A2012="FES.574334;IEC_symbol\;1\;146\;6;;FES.574334;IEC_symbol\;1\;146\;6;MURR.7000-41211-0000000;MURR.7000-12221-6341000;Artikelnummer;;1;1"/>
</root>
Nun du willst Daten von einem SQL-Server haben. Dann würde ich zunächst einmal danach suchen, wie man das mit dem SQL-Server macht.
Wenn du das herausgefunden hast, dann schaust du, wie man das in C# schreibt.
BTW Stake Overflow Die Seite heißt StackOverflow und das ist ein bekannter Fehler beim rekursiven Programmieren (wenn man die Abbruchbedingung vergessen hat oder es wirklich tief in den Kaninchenbau geht)
Halten wir fest, bei mir fliegt so etwas im Review heraus. Sollte die Implementierung nach Lehrbuch Schwierigkeiten machen (zu aufwendig, zu langsam, ...) dann würde ich auch einen pragmatischen Ansatz verfolgen. Aber erst dann.
Zitat von Th69
Technisch kann man zwar MVVM auch für WinForms benutzen, jedoch sind View und ViewModel meistens doch logisch voneinander abhängig, so daß man für eine neue UI-Technologie auch häufig die VMs anpassen muß (wenn es um mehr geht als das Binden von Strings und Zahlenwerten, z.B. UI-technologische Datentypen).
Edit:
Als Beispiel für einen UI-technologischen Datentyp die Anzeige eines Bildes:
- für WinForms: System.Drawing.Image/Bitmap
- für WPF: System.Windows.Media.ImageSource
Wenn man im ViewModel
Datentypen aus dem UI-Framework verwendet, dann hat man schon im Ansatz etwas falsch gemacht. So etwas sollte bei jedem Review sofort gerügt werden.
Nehmen wir mal das Beispiel mit dem Bild und wie man das bei WPF/MAUI macht:
Im ViewModel
eine Eigenschaft vom Typ byte[]
(Bild-Rohdaten) oder string
(Verweis auf Bild per Dateiname oder URL) erstellen und diese Eigenschaft in der View
an die Source
Eigenschaft des Image
Controls binden.
qed
Ich hätte hier mit await Task.Yield()
gearbeitet, das funktioniert bei mir mit den Dialogen immer sehr gut.
Versuch doch mal die App.xaml
exakt genau so wie ich die gepostet habe.
Genau aus diesem Grund habe ich die auch komplett gepostet
Weil du irgendwo auch sagen musst, was er wie wo laden soll. Z.B. in der App.xaml
weil das für die gesamte Anwendung gilt:
<Application x:Class="WpfAppToolBar.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfAppToolBar"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Themes/Generic.xaml" />
<ResourceDictionary Source="Themes/GenericSeite2.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
Weil dir zu deinem Control noch ein Style fehlt. Ohne Style weiß WPF doch nicht wie es das darstellen soll. Ich habe es dir mal in die App.xaml
eingebaut:
<Application x:Class="WpfAppToolBar.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfAppToolBar"
StartupUri="MainWindow.xaml">
<Application.Resources>
<Style TargetType="{x:Type local:NavigationSeite2}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:NavigationSeite2}">
<ContentPresenter ContentSource="Text"
TextElement.Foreground="{TemplateBinding Foreground}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Application.Resources>
</Application>
So, mit der OneDrive Version 23.169.0813.0001 ist das behoben worden.
Wenn ich so deine Beschreibung lese und die (erste) Frage dazu, dann frage ich mich ob du das wirklich ernst meinst.
Ich füge der Liste immer wieder etwas an. Wird das jetzt immer länger, wenn ich die nicht leere?
Und wo und wann ein Clear erforderlich ist ... äh, ja dann, wenn es die Situation - die bislang nur du kennst - erfordert.
Das Laden der Daten sollte nicht durch den Konstruktor angestossen werden. Es ist wesentlich geschickter dieses erst dann zu erledigen, wenn dieses erforderlich ist (z.B. wenn die View wirklich angezeigt wird).
Meine ViewModels basieren alle auf:
public abstract class ViewModelBase : ReactiveObject
{
[Reactive] public bool IsInitialized { get; private set; }
public async Task InitializeAsync( CancellationToken cancellationToken = default )
{
IsInitialized = false;
await OnInitializeAsync( cancellationToken );
IsInitialized = true;
}
protected virtual Task OnInitializeAsync( CancellationToken cancellationToken ) => Task.CompletedTask;
}
Die konkreten ViewModels überschreiben die OnInitializeAsync
-Methode wenn es irgendwelche Daten zu laden gibt.
Per DependencyInjection bekommt jede View (Window, Page) das ViewModel
im Konstruktor übergeben und beim Erscheinen der View
wird die Initialisierung des ViewModels
angestossen.
public class MainWindow : Window
{
public MainWindow( MainWindowViewModel viewModel )
{
InitializeComponent();
DataContext = viewModel;
Appearing += async ( s, e ) => await viewModel.InitializeAsync();
}
}
Das funktioniert wie gesagt bei einem Window
als auch bei einer Page
ganz wunderbar.
So am Rande bemerkt:
Bei der aktuellen Definition wird es im Übrigen schwierig werden zwischen nichts gewählt (also alle Bits auf 0) und StdVerzListenFlag.DESKTOP
zu unterscheiden, denn beide Zustände haben den Wert 0
.
Wie löst man das, wenn man dem Peter erzählt er soll doch bitte das Geld einstecken und dann mit dem Herbert zum Essen fährt und nicht bezahlen kann?
Nimm den zum Essen mit, der das Geld eingesteckt hat, wenn du ernsthaft bezahlen möchtest.
Mit den Objekten und Instanzen verhält es sich genauso. Obwohl Peter und Herbert beide vom Typ Mensch sind unterscheiden sich die Instanzen eben dadurch das die Instanz Peter das Geld hat und die Instanz Herbert eben nicht.
public class Mensch
{
public decimal Geld { get; set; }
}
var peter = new Mensch();
peter.Geld += 100;
var herbert = new Mensch();
Du arbeitest mit DREI Instanzen vom LoginVM
.
Die erste Instanz erzeugst du im BasicWindowVM
namespace WpfVisible.ViewModel
{
public class BasicWindowVM : BaseViewModel
{
public BaseViewModel ViewModel { get; set; }
public BasicWindowVM()
{
ViewModel = new LoginVM(); // <<== ERSTE Instanz
}
}
}
und die zweite Instanz in der BasicWindowView
<Window x:Class="WpfVisible.View.BasicWindowView"
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:WpfVisible.View"
xmlns:vm="clr-namespace:WpfVisible.ViewModel"
xmlns:converter="clr-namespace:WpfVisible.ViewModel.Converters"
mc:Ignorable="d"
Title="BasicWindowView"
Height="450"
Width="800">
<Window.DataContext>
<vm:BasicWindowVM />
</Window.DataContext>
<Window.Resources>
<!-- ZWEITE Instanz -->
<vm:LoginVM x:Key="LoginVM" />
<converter:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
</Window.Resources>
<Grid>
<DockPanel>
<ToggleButton DockPanel.Dock="Top"
Content="Toggle"
Visibility="{Binding Source={StaticResource LoginVM}, Path=IsAuthenticated, Mode=OneWayToSource, Converter={StaticResource BooleanToVisibilityConverter}}" />
<!--Visibility="{Binding Source={StaticResource LoginVM}, Path=IsAuthenticated, Converter={StaticResource BooleanToVisibilityConverter}}"-->
<ContentControl Content="{Binding ViewModel}" />
</DockPanel>
</Grid>
</Window>
und die dritte im LoginView
<UserControl x:Class="WpfVisible.View.LoginView"
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:local="clr-namespace:WpfVisible.View"
xmlns:vm="clr-namespace:WpfVisible.ViewModel"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.DataContext>
<!-- DRITTE Instanz -->
<vm:LoginVM/>
</UserControl.DataContext>
<Grid>
<Button Content="Login" VerticalAlignment="Center" HorizontalAlignment="Center" Width="200" Command="{Binding LoginCommand}"/>
</Grid>
</UserControl>
Der Login-Button ist mit der dritten Instanz verknüpft und der ToggleButton mit der zweiten Instanz. Da ist es auch kein Wunder, dass dann nichts passiert.
Das Positive: Mehr falsch machen kann man fast nicht mehr.
Hier nun die Änderungen, die notwendig sind:
BasicWindowView.xaml
<Window x:Class="WpfVisible.View.BasicWindowView"
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:WpfVisible.View"
xmlns:vm="clr-namespace:WpfVisible.ViewModel"
xmlns:converter="clr-namespace:WpfVisible.ViewModel.Converters"
mc:Ignorable="d"
Title="BasicWindowView"
Height="450"
Width="800">
<Window.Resources>
<converter:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
</Window.Resources>
<Window.DataContext>
<vm:BasicWindowVM />
</Window.DataContext>
<Grid>
<DockPanel>
<ToggleButton DockPanel.Dock="Top"
Content="Toggle"
Visibility="{Binding ViewModel.IsAuthenticated, Converter={StaticResource BooleanToVisibilityConverter}}" />
<ContentControl Content="{Binding ViewModel}" />
</DockPanel>
</Grid>
</Window>
LoginView.xaml
<UserControl x:Class="WpfVisible.View.LoginView"
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:local="clr-namespace:WpfVisible.View"
xmlns:vm="clr-namespace:WpfVisible.ViewModel"
mc:Ignorable="d"
d:DesignHeight="450"
d:DesignWidth="800">
<Grid>
<Button Content="Login"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Width="200"
Command="{Binding LoginCommand}" />
</Grid>
</UserControl>
BaseViewModel.cs
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace WpfVisible.ViewModel
{
public abstract class BaseViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged( [CallerMemberName] string propertyName = null )
{
PropertyChanged?.Invoke( this, new PropertyChangedEventArgs( propertyName ) );
}
private bool isAuthenticated;
public bool IsAuthenticated
{
get { return isAuthenticated; }
set { isAuthenticated = value; OnPropertyChanged(); }
}
}
}
Das ist der Logik hinter dem ToggleButton
völlig egal, von wem und woher er die Information bekommt, er muss sie nur bekommen und die Benachrichtigung muss funktionieren, dann arbeitet der wie zu erwarten und genau das sollte das Beispielprojekt zeigen (nicht mehr).
Also an dem ToggleButton liegt es definitiv nicht. Siehe Projekt im Anhang.
Dein Hauptproblem ist der Binding-Mode OneWayToSource
Siehe dazu Übersicht über Datenbindung - Richtung des Datenflusses
So sollte das funktionieren
<ToggleButton
HorizontalAlignment="Left"
Width="50"
Visibility="{Binding Source={StaticResource LoginVM}, Path=MenuVisibility, Mode=OneWay}"
Command="{Binding OpenMainMenuCommand}">
Das Setzen von UpdateSourceTrigger
ist überflüssig, denn eine Änderung der Eigenschaft erfolgt doch gar nicht über die View.
Das Setzen von Mode
ist auch überflüssig, da es sich bei OneWay
um den Default-Wert handelt.
Darüber hinaus sollte man im ViewModel keine Typen vom UI-Layer/-Framework verwenden (wie z.B. hier Visibility
). Hier macht es wesentlich mehr Sinn im ViewModel eine Eigenschaft vom Typbool
zu haben (denkbarer Name wäre IsAuthenticated
) und der Bindung dann einen Converter an die Hand zu geben, der diesen bool
Wert in den passenden Visibility
Wert konvertiert. Damit lässt man dem UI-Designer alle Freiheiten zur Darstellung.
Kann mir jemand erklären, warum der Einstellungsdialog von identischen OneDrive-Versionen auf zwei nahezu identischen Systemen (VMware) so unterschiedlich aussieht?
Den moderneren Dialog bekomme ich auf dem System wo auch Visual Studio 2022 installiert ist, falls es da einen Zusammenhang gibt.
Was sagt denn der Stacktrace wenn du einen Breakpoint auf die Zeile _candleKeyLevel = fixedProfileOriginScale;
setzt?
Das sollte deine Frage eigentlich hinreichend beantworten.
Hast du dabei bedacht, dass ein fehlgeschlagener INSERT trotzdem den Auto-Inkrement Wert erhöht?
Wenn du damit leben kannst ist alles ok. Ich sah allerdings schon so einige in einer ähnlichen Situation aus allen Wolken fallen.
Also ich kann keinen Unterschied feststellen.
<Grid BackgroundColor="#c0e1e1" />
<Grid Background="#c0e1e1" />
BackColor = Color.FromArgb( 192 , 225 , 225 );
Und was dabei rauskommt (MAUI, WPF, WinForms) sieht man im Screenshot
Den Weg der doppelten Konvertierung musst du nicht gehen, es reicht ein simpler Cast IDNrHaupt = (int)DR["IDNrHaupt"]
EDIT: Oh, zwei Stühle eine Meinung ...
Stell dir einmal vor so ein Control wie die TextBox
wäre so konzipiert wie dein UserControl
- dann könntest du dieses Binding
<TextBox Text="{Binding FirstName}"/>
nicht einfach so machen, sondern du müsstest im CodeBehind auf den DataContext
dieser TextBox
zugreifen und dort der Eigenschaft Text
den entsprechenden Wert zuweisen. Sehr gruselig.
Gottlob wurde das nicht so gemcht und es gibt eben diese DependencyProperty
.
Eine win32.dll
kenne ich von Windows nicht. Meinst du eventuell die Windows-API (formerly known as Win32-API)?
Dann sollte das eigentlich deine Frage beantworten:
Mithilfe der Windows-API können Sie Anwendungen entwickeln, die auf allen Windows-Versionen erfolgreich ausgeführt werden, und gleichzeitig die für jede Version einzigartigen Features und Funktionen nutzen. (Beachten Sie, dass dies früher als Win32-API bezeichnet wurde. Der Name Windows-API spiegelt seine Wurzeln in 16-Bit-Windows und seine Unterstützung unter 64-Bit-Windows genauer wider.)
Quelle: Windows-API-Index
Generell ist es eine gute Idee, sich beim Hersteller zu erkundigen.
Zitat von Kriz
-> Würde das hier gern schöner formatieren, aber es wird leider nicht richtig übernommen...
Du hast für deinen Code(-Block) die Code Formatierung verwendet und nicht den direkt daneben liegenden Button für Code-Block einfügen.
Mit Code-Block einfügen sieht das dann so aus:
switch (overlay.Type)
{
case OverlayType.Ellipse:
ShowEllipse = true;
ShowRectangle = false;
ShowPath = false;
break;
case OverlayType.Rectangle:
ShowEllipse = false;
ShowRectangle = true;
ShowPath = false;
break;
case OverlayType.Path:
ShowEllipse = false;
ShowRectangle = false;
ShowPath = true;
break;
default:
break;
}
Die Code Formatierung verwendest du, wenn du im Text etwas als Code formatieren möchtest, wie z.B. den Typen string
oder deinen overlay.Type
.
WÄre es nicht einfacher so?
public bool ShowEllipse => overlay.Type == OverlayType.Ellipse;
public bool ShowRectangle => overlay.Type == OverlayType.Rectangle;
public bool ShowPath => overlay.Type == OverlayType.Path;
und immer wenn sich in overlay
die Eigensschaft Type
ändert, dann folgenden Code noch ausführen
OnPropertyChanged(nameof(ShowEllipse));
OnPropertyChanged(nameof(ShowERectangle));
OnPropertyChanged(nameof(ShowPath));
Alternativ gäbe es auch noch diesen EnumToBoolConverter
aus dem CommunityToolkit
Zitat von RobertStahl
Perfekt, danke, aber das @GWu1 wird anscheinend benötigt für die Zuweisung im Update-Befehl
Ja, ähm ... genau ... ich habe doch auch nicht gesagt "entferne das @ Zeichen" sondern du musst bei Parameters.Add
den Parameter-Namen so verwenden wie du ihn im Statement geschrieben hast. Und zwar genau so.
Denn
Parameters can be prefixed with either
:
,@
, or$
.
aber für einen Präfix musst du dich zwingend entscheiden und der Parameter-Name ist immer mit Präfix anzugeben.
Wenn du es allerdings ganz bequem haben möchtest, dann kannst du auch Dapper verwenden. Dann würde das so aussehen:
class GrenzwerteDto
{
public int ProductReference { get; set; }
public decimal GWu1 { get; set; }
}
connection.Open();
var data = new GrenzwerteDto { ProductReference = 42, GWu1 = 12.45, };
connection.Execute( "UPDATE Grenzwerte SET GWu1 = @GWu1 WHERE REF_Produkt = @ProductReference", data );
oder mit noch weniger Boilerplate
connection.Open();
connection.Execute( "UPDATE Grenzwerte SET GWu1 = @GWu1 WHERE REF_Produkt = @ProductReference",
new { ProductReference = 42, GWu1 = 12.45, } );
Kann man sich überlegen
Da sind drei Dinge falsch.
command.CommandText = $"UPDATE Grenzwerte SET GWu1 = '@GWu1' WHERE REF_Produkt = 'Int aus einer Textbox'
Die Parameter kümmrn sich von ganz alleine darum, dass die Werte korrekt übergeben werden. Jede weitere Bevormundung durch Anführungszeichen o.ä. empfinden diese als übergriffig.
So ist es korrekt
command.CommandText = $"UPDATE Grenzwerte SET GWu1 = @GWu1 WHERE REF_Produkt = 'Int aus einer Textbox'
Parameters.Add
verwendenStatt
command.Parameters.AddWithValue("GWu1", DbType.Decimal).Value = NudGw_Gwu1.Value;
so
command.Parameters.Add("GWu1", DbType.Decimal).Value = NudGw_Gwu1.Value;
Der Name des Parameters lautet exakt so wie er in dem Command-Text angegeben wurde - wirklich exakt und kein "so irgendwie in der Art evetuell"
Wenn dort der Parameter also als @GWu1
angegeben wurde, dann ist genau das auch der Name.
Also statt
command.Parameters.Add("GWu1", DbType.Decimal).Value = NudGw_Gwu1.Value;
so
command.Parameters.Add("@GWu1", DbType.Decimal).Value = NudGw_Gwu1.Value;
Es ist etwas konfus was du da schreibst ... du könntest ruhig etwas konkreter werden, dann könnte man auch konkreter Hilfestellung geben.
Worauf du dich mit getters/setters beziehst erschließt sich mir nicht (im Code von Palladin sehe ich nur Getter).
Hast du dir das Spezification Pattern mal angesehen? Das ist eigentlich für so etwas der richtige Ansatz.
Hallo, du hast den klassischen Anfängerfehler (nicht falsch verstehen, den macht gefühlt jeder Programmierer auf seiner Reise - ich auf jeden Fall auch) gemacht.
Wenn du ein SQL-Statement per string zusammenbaust, dann ist das ein grober Fehler - Grüße von Little Bobby Tables.
Sicherer und einfacher funktioniert das mit Parametern denn die Parameter sorgen dafür, dass die Werte beim SQL-Server auch korrekt ankommen.
Ich sprach eigentlich von diesem VERSIONINFO
und nicht von System.Version
, denn dort passt es problemlos, weil dort für Build (und auch die anderen Teile) ein Int32
verwendet wird.
Wenn der Build bei 100.000 anfangen soll wird dann auch die Struktur in VERSIONINFO geändert?
Dort wird die Version ja als 64bit Wert angelegt (4x 16bit = 0..65535).
Meine Glaskugel ist in dem Bereich aber ganz wolkig, somit lassen wir uns überraschen.
Da wir nicht wissen, wie die Versionsnummern in der Zukunft weitergezählt werden, sollte man aber auch zwingend Major und Minor daraufhin prüfen, ob diese auch wirklich 10 bzw. 0 sind. Sonst ist die Verwirrung groß wenn (warum auch immer) Windows 12 die Version 10.1.12345.0 hat.
Kannst du mal mit DISKPART die Attribute des Laufwerks prüfen?
DISKPART
SELCT DISK 6
ATTRIBUTES DISK
Dann sollte er so etwas anzeigen
Aktueller schreibgeschützter Zustand: Nein
Schreibgeschützt : Nein
Startdatenträger : Nein
Auslagerungsdatei-Datenträger : Nein
Ruhezustandsdatei-Datenträger : Nein
Absturzabbild-Datenträger : Nein
Clusterdatenträger : Nein
Eventuell ist bei Windows 10 dort der Schreibschutz drin.
Probier mal diese kleine Änderung am Code:
public void AppendText(string text)
{
_text += text;
this.StateHasChanged();
}
Das riecht ein wenig nach Specification Pattern