Laden...

Forenbeiträge von Caveman Ingesamt 187 Beiträge

31.01.2024 - 00:37 Uhr

Servus,

im angehängten Projekt sollte das mit DI klappen.

22.01.2024 - 16:17 Uhr

Jetzt ist der Groschen gefallen, was gemeint war!

Allerdings rufe ich die Methode Create1DModelData() in meinem Beispiel nur einmal auf, nämlich im Konstruktor.

Deshalb ist das nicht zutreffend. Mir ist schon klar, dass ich das bei mehrmaligem Methodenaufruf nicht machen darf.

Hintergrund: Es handelt sich um ein Testprojekt, in dem ich meine ganzen Versuche in eigene Methoden ausgelagert habe. Im Eingangspost habe ich dann die falsche Zeile gelöscht. In dem Testprojekt werden nur Datenstrukturen erzeugt, die im DataGrid angezeigt werden.

22.01.2024 - 15:05 Uhr

@TH69: Das habe ich auch schon durchgelesen. Weiter unten in dem Thread wird das DataGrid2D-Control erwähnt, welches auch eine DataTable im Hintergrund verwendet.

@Alf Ator: Tut mir leid, aber ich weiß überhaupt nicht, was Du mir mitteilen willst. In Deinem Bild wird eine Spalte gezeigt. Wie kommst Du auf - sagen wir mal - 50 Spalten?

Ich möchte im Prinzip eine n,m-Matrix von Model oder meinetwegen CellViewModel an die DataGrid binden.

Edit: Ich habe im Übrigen auch die Antwort von Abt nicht verstanden, obwohl ich mir das mindestens 10x durchgelesen habe.

22.01.2024 - 13:57 Uhr

Nach all dem was ich bis bis jetzt gelesen habe, kann man offenbar keine zweidimensionale Liste an das Datagrid binden.

Ich werde es jetzt erstmal mit einer DataTable als ItemsSource weiter versuchen.

20.01.2024 - 17:16 Uhr

Arrghh, habe im ViewModel die falsche Zeile rausgelöscht beim Bereinigen!

Statt

public ObservableCollection<Model> Items { get; set; }

muss es lauten

public ObservableCollection<Model> ItemsModel1D { get; set; }
20.01.2024 - 14:58 Uhr

Hallo,

ich habe mit OpenXML eine Excedatei mit ca. 5800 Zeilen und 175 Spalten in eine List<List<T>> Struktur eingelesen, wobei T eine Zelle darstellt. T enthält mehrere Properties, aber nur eines davon soll im DataGrid dargestellt werden,

Leider schaffe ich es nicht, diese Datenstruktur an das DataGrid zu binden und Onkel Google ist nicht sehr hilfreich!

Eine List<T> bekomme ich noch wie folgt dargestellt.

Wie muss ich weiter vorgehen, damit ich eine List<List<T>> an das DataGrid binden kann?

    public class Model
    {
        public string? UnImportantValue1 { get; set; }

        public string? UnImportantValue2 { get; set; }

        public string CellValue { get; set; }
    }
    public class MainWindowViewModel
    {
        public ObservableCollection<Model> Items { get; set; }

        public ICommand ColumnGeneratingEvent { get; set; }

        public MainWindowViewModel()
        {
            ColumnGeneratingEvent = new CcActionCommand(OnAutoGeneratingColumnExecuted, null);
            Create1DModelData();
        }

        private void Create1DModelData()
        {
            ItemsModel1D = new ObservableCollection<Model>();
            for (int row = 0; row < 10; row++)
            {
                ItemsModel1D.Add(new Model() { CellValue = $"Row {row} - Col 0", UnImportantValue1 = "Blah", UnImportantValue2 = "Blubb" });
            }
        }

        private void OnAutoGeneratingColumnExecuted(object obj)
        {
            if (obj is DataGridAutoGeneratingColumnEventArgs eventArgs)
            {
                eventArgs.Column.Header = "Header";
            }
        }
    }
        <!--ItemsModel1D DataGrid-->
        <DataGrid x:Name="TestDataGrid"
                  AlternatingRowBackground="LightSlateGray"
                  HorizontalAlignment="Stretch"
                  VerticalAlignment="Stretch"
                  AutoGenerateColumns="False"
                  SelectionUnit="Cell"
                  SelectionMode="Extended"
                  CanUserAddRows="False"
                  CanUserDeleteRows="False"
                  CanUserSortColumns="False"
                  CanUserReorderColumns="False"
                  EnableColumnVirtualization="True"
                  EnableRowVirtualization="True"                  
                  ItemsSource="{Binding ItemsModel1D}">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Header" Binding="{Binding CellValue}" />
            </DataGrid.Columns>
            <behav:Interaction.Triggers>
                <behav:EventTrigger EventName="AutoGeneratingColumn" SourceObject="{Binding ElementName=TestDataGrid}" >
                    <behav:InvokeCommandAction Command="{Binding ColumnGeneratingEvent, Mode=OneWay}" PassEventArgsToCommand="True" />
                </behav:EventTrigger>
            </behav:Interaction.Triggers>
        </DataGrid>
16.01.2024 - 22:26 Uhr

Hallo,

das handhabe ich auch so.

Grundsätzlich wollte ich nicht zu viel ändern, weil

  1. ich zu faul war noch mehr im Notepad++ zu schreiben.
  2. der Code noch irgendwelche Ähnlichkeit zum Ursprungscode haben sollte.
16.01.2024 - 00:05 Uhr

Servus,

wenn ich alles richtig verstanden habe, dann vielleicht so (ungetestet)

public App()
{
    Ioc.Default.ConfigureServices(

        new ServiceCollection()
            .AddSingleton<MainWindow>()
            .AddSingleton<MainWindowViewModel>()
            .AddTransient<IUserService, UserService>()

            .BuildServiceProvider() );

    MainWindow mainWindow = Ioc.Default.GetRequiredService<MainWindow>();
	mainWindow.DataContext = Ioc.Default.GetRequiredService<MainWindowViewModel>();
    mainWindow.Show();
}
public MainWindow()
{
    InitializeComponent();
}
public ObservableCollection<string> Usernames { get; private set; } = new ObservableCollection<string>();

    public RelayCommand AddNameButton { get; set; }
    private readonly IUserService userService;
	
    private string _inputName;
    public string InputName
    {
        get { return _inputName; }
        set
        {
            _inputName = value;
            OnPropertyChanged();
        }
    }

    public MainWindowViewModel(IUserService userService)
    {
	    this.userService = userService;
        AddNameButton = new RelayCommand(() =>
        {
		    Usernames.Clear();
            Usernames = userService.GetUsers(InputName);
        });
    }
}
    public ObservableCollection<string> Usernames { get; private set; } = new ObservableCollection<string>();

    public UserService()
    {
    }
	
    public ObservableCollection<string> GetUsers(string name)
    {
        Usernames.Add(name);
        return Usernames;
    }
}
16.11.2023 - 16:52 Uhr

Ich habe auf meinen Rechnern keine Virenscanner installiert!

20.10.2023 - 22:44 Uhr

Ich bekomme als Ergebnis 1259

20.09.2023 - 19:45 Uhr

Das funktioniert wahrscheinlich nicht, da der Namespace nicht stimmt. In der Datei Page2.xaml ist local auf WpfAppToolBar.Pages definiert. NavigationSeite2 liegt aber im Namespace WpfAppToolBar.

Eine Änderung in Page2.xaml sollte das Problem beheben.

Statt

<local:NavigationSeite2 Text="Warum geht das nicht?"/>

das hier

<n:NavigationSeite2 Text="Warum geht das nicht?"/>
09.09.2023 - 18:20 Uhr

Match hat doch die Eigenschaft Success.

Match match = pattern.Match(input);
if (match is not null && match.Success ) 
{
    Console.WriteLine("Hat gematcht!");
}
else
{
    Console.WriteLine("Hat nicht gematcht!");
}
26.08.2023 - 11:12 Uhr

Tausche den ContentPresenter gegen einen GridViewRowPresenter!

<!--<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
					  SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
					  VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />-->
<GridViewRowPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
					  SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
					  VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
24.08.2023 - 23:10 Uhr

Hallo,

ich habe für Excel ein AddIn erstellt, das im Wesentlichen nur Tabellenblatter kopieren soll und auf einem neuen Tabellenblatt Formeln einträgt.

Das funktioniert auch alles.

Das AddIn habe ich veröffentlicht und mit dem Setup auf einem anderen Computer installiert. Das AddIn wird Angezeigt, auch wenn das Ribbon nicht so ist wie auf dem Entwicklungscomputer.

Allerdings dauert es mehrere Sekunden, bis der Button als aktiv angezeigt wird. Auch dauert es mehrere Sekunden, bis der Code ausgeführt wird.

Woran kann das liegen?

24.08.2023 - 23:02 Uhr

Ja, es geht darum, dass sich nicht die konsumierenden Klasse um die Aufgaben kümmern müssen, sondern diese Verantwortichkeiten in der jeweiligen Klasse bleibt. Bin aber nicht so der Erklärbär 😃

Habe mal in Anlehnung an deinem Beispiel was gebastelt.

    public interface IDoSomething
    {
        List<string> List { get; set; }

        string Sort();
    }
    
    public class DoSomething : IDoSomething
    {
        public List<string> List { get; set; }

        public DoSomething()
        {
            List = new List<string>();
        }

        public string Sort()
        {
            return List.ElementAt(1);
        }
    }
    
        public class DoSomethingElse : IDoSomething
    {
        public List<string> List { get; set; }

        public DoSomethingElse()
        {
            List = new List<string>();
        }

        public string Sort()
        {
            return List.ElementAt(0);
        }
    }

    public class Worker
    {
        private IDoSomething doSomething;

        public List<string> List
        {
            get { return doSomething.List; }
            set { doSomething.List = value; }
        }

        public Worker(IDoSomething doSomething)
        {
            this.doSomething = doSomething;
        }

        public void Add(string item)
        {
            doSomething.List.Add(item);
        }

        public string Execute()
        {
            return doSomething.Sort();
        }
    }
    internal class Program
    {
        static void Main(string[] args)
        {
            Worker worker1 = new(new DoSomething());
            Worker worker2 = new(new DoSomethingElse());

            for (int i = 0; i < 10; i++)
            {
                worker1.Add($"item {i:D2}");
                worker2.Add($"item {i:D2}");
            }

            Console.WriteLine($"Worker1: Sort => {worker1.Execute()}");
            Console.WriteLine($"Worker2: Sort => {worker2.Execute()}");
            Console.ReadKey();
        }
    }
14.08.2023 - 21:23 Uhr

Ein paar Beispiele gibt es auf StackOverflow

07.08.2023 - 22:35 Uhr

Vielleicht hilft das weiter:

Xaml:

<Window x:Class="MyCSharp125410.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:MyCSharp125410"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    
    <Window.DataContext>
        <local:MainWindowViewModel />
    </Window.DataContext>
    
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="auto" />
        </Grid.RowDefinitions>
        <TreeView Name="myTreeView" Grid.Row="0" ItemsSource="{Binding Nodes}">
            <TreeView.ItemContainerStyle>
                <Style TargetType="{x:Type TreeViewItem}">
                    <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
                    <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
                    <Setter Property="FontWeight" Value="Normal" />
                    <Style.Triggers>
                        <Trigger Property="IsSelected" Value="True">
                            <Setter Property="FontWeight" Value="ExtraBold" />
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </TreeView.ItemContainerStyle>
            <TreeView.ItemTemplate>
                <HierarchicalDataTemplate ItemsSource="{Binding Children}">
                    <TextBlock Text="{Binding Name}" />
                </HierarchicalDataTemplate>
            </TreeView.ItemTemplate>
        </TreeView>
        <Button x:Name="AddNodeButton" 
                Grid.Row="1" 
                Content="Add Child-Node to Node 05" 
                Command="{Binding AddNodeCommand}"/>
    </Grid>
</Window>

Das ViewModel:

using CommunityToolkit.Mvvm.Input;
using System.Collections.ObjectModel;
using System.Windows.Input;

namespace MyCSharp125410
{
    public class MainWindowViewModel
    {
        public ObservableCollection<Node> Nodes { get; set; }

        public ICommand AddNodeCommand { get; private set; }

        public MainWindowViewModel()
        {
            Nodes = new ObservableCollection<Node>
            {
                new Node() { Name = "Node 01" },
                new Node() { Name = "Node 02" },
                new Node() { Name = "Node 03" },
                new Node() { Name = "Node 04" },
                new Node() { Name = "Node 05" },
                new Node() { Name = "Node 06" }
            };

            Nodes[1].Children.Add(new Node() { Name = "Node 02.1" });

            AddNodeCommand = new RelayCommand(OnAddNodeExecuted);
        }

        private void OnAddNodeExecuted()
        {
            Nodes[4].Children.Add(new Node() { Name = $"Node 05.{Nodes[4].Children.Count + 1}" });
        }
    }
}

Und ein Node Model:

using System.Collections.ObjectModel;

namespace MyCSharp125410
{
    public class Node
    {
        public string Name { get; set; }

        public ObservableCollection<Node> Children { get; set; }

        public Node() 
        {
            Children = new ObservableCollection<Node>();
        }

    }
}

In dem Beispiel habe ich das CommunityToolkit.Mvvm wegen dem RelayCommand noch über Nuget installiert.

Wenn alles zusammengerührt ist, dann sollte bei jedem Klick auf den Button ein neuer Child-Knoten im Node 05 erstellt werden.
09.07.2023 - 14:51 Uhr

Aha, doch so einfach! 😃

Danke Dir!

09.07.2023 - 09:57 Uhr

Hallo zusammen,

ich will von einer SMA WebBox die Parameter auslesen. Die Kommunikation erfolgt über UDP und im JSON Format. Der JSON String wird über System.Text.Json serialisiert bzw. deserialisiert.

Mein Problem ist nun, dass ich das byte-Array für das Senden so aufbereiten muss, dass jedes Zeichen mit 2 Bytes enthalten ist. Im Moment mache ich das indem ich ein zweites byte-Array mit doppelter Länge erzeuge und die Werte entsprechen umkopiere und ergänze.

Also aus der Bytefolge 123 34 102 111 114 muss ein 123 0 34 0 102 0 111 0 114 0 werden.

// Send
udpClient.Connect(webBoxEndPoint);
byte[] sendBytes = Encoding.UTF8.GetBytes(requestMessage);

byte[] sendBytes2 = new byte[sendBytes.Length * 2];
int index = 0;
foreach (byte b in sendBytes)
{
    sendBytes2[index++] = b;
    sendBytes2[index++] = 0;
}
int sent = await udpClient.SendAsync(sendBytes2, sendBytes2.Length);

Beim Empfang der Daten muss die 0 dann wieder entfernt werden, damit der Json Deserialiser nicht meckert.

// Receive
UdpReceiveResult result = await udpClient.ReceiveAsync();
string responseMessage = Encoding.UTF8.GetString(result.Buffer).Replace("\0", "");

Meine Frage zielt nun darauf ab, ob man das Erstellen des byte-Arrays mit zwei Bytes pro Zeichen aus dem String nicht einfacher/eleganter lösen kann. Und natürlich auch der umgekehrte Weg.

05.07.2023 - 22:57 Uhr

Ist schon spät heute, aber nur soviel. Das LoginVM wird mehrfach instanziert. Ist zwar jetzt nicht die Lösung aber nur so als Hinweis.

11.06.2023 - 19:12 Uhr

(?<Bsb1>^.*?a)(?<Bsb2>.*?e).*$

31.05.2023 - 23:04 Uhr

Hallo zusammen,

ich versuche mich an meinem ersten Blazor Server Projekt und will dafür das Paket LiveChart verwenden. Als erstes habe ich stur den Beispielcode von der LiveChart Doku reinkopiert. Wenn ich das Projekt starte wird eine NullReferenceException (ExecutionContext.cs) geworfen.

Bei enem Blazor-WebAssembly Projekt ist dies nicht der Fall. Da wird das Chart sauber angezeigt mit dem gleichen Code.

Was ist zu tun, damit das auf Blazor-Server lauffähig wird?

31.05.2023 - 22:52 Uhr

Du kannst das Community Toolkit MVVM verwenden.

[ObservableProperty]
private Bitmap _bitmap;
27.04.2023 - 19:09 Uhr

Zitat von EmilDev

ADUserSuggestionsListBox.Visibility = Visibility.Hidden;

Das müsste dann wahrscheinlich Visibility.Visible sein.

Ansonsten könnte man auch für die Controls im Xaml Namen vergeben.

23.04.2023 - 22:30 Uhr

Servus, eine nicht ganz MVVM konforme Lösung

    <Window.Resources>
        <Style x:Key="PasswordBoxStyle"
               TargetType="PasswordBox">
            <Setter Property="Background" Value="LightGreen"/>
            <Style.Triggers>
                <DataTrigger Binding="{Binding PasswordsAreEqual}" Value="{x:Static sys:Boolean.FalseString}">
                    <Setter Property="Background" Value="Red" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

        <PasswordBox x:Name="PasswordBox1"
                     Grid.Row="0"
                     Tag="Password1"
                     PasswordChar="*"
                     Style="{StaticResource PasswordBoxStyle}">
            <behav:Interaction.Triggers>
                <behav:EventTrigger EventName="PasswordChanged">
                    <behav:InvokeCommandAction Command="{Binding PasswordChanged, Mode=OneWay}" 
                                               CommandParameter="{Binding ElementName=PasswordBox1}" />
                </behav:EventTrigger>
            </behav:Interaction.Triggers>
        </PasswordBox>

        <PasswordBox x:Name="PasswordBox2"
                     Grid.Row="1"
                     Tag="Password2"
                     PasswordChar="*"
                     Style="{StaticResource PasswordBoxStyle}">
            <behav:Interaction.Triggers>
                <behav:EventTrigger EventName="PasswordChanged">
                    <behav:InvokeCommandAction Command="{Binding PasswordChanged, Mode=OneWay}" 
                                               CommandParameter="{Binding ElementName=PasswordBox2}" />
                </behav:EventTrigger>
            </behav:Interaction.Triggers>
        </PasswordBox>
    </Grid>
    public class MainViewModel : ViewModelBase
    {
        #region Fields
        private bool passwordsAreEqual;
        #endregion

        #region Properties
        public SecureString Password1 { get; set; }

        public SecureString Password2 { get; set; }

        public bool PasswordsAreEqual
        {
            get { return passwordsAreEqual; }
            set
            {
                if (passwordsAreEqual != value)
                {
                    passwordsAreEqual = value;
                    OnPropertyChanged();
                }
            }
        }

        public ICommand PasswordChanged { get; private set; }
        #endregion

        #region Constructors
        public MainViewModel()
        {
            PasswordChanged = new RelayCommand(OnPasswordChangedExecuted);
        }
        #endregion

        #region Methods
        private void OnPasswordChangedExecuted(object obj)
        {
            if (obj is PasswordBox passwordBox)
            {
                if (passwordBox.Name.Equals("PasswordBox1"))
                {
                    Password1 = passwordBox.SecurePassword;
                }
                else
                {
                    Password2 = passwordBox.SecurePassword;
                }
            }

            PasswordsAreEqual = SecureStringToPlainString(Password1).Equals(SecureStringToPlainString(Password2)) ? true : false;
        }
        #endregion
    }
17.04.2023 - 22:04 Uhr

Eine Möglichkeit

    internal class Program
    {
        static string[] obstkorb = { "Apfel", "Orange", "Moehre", "Banane", "Birne" };
        static string[] obstliste = { "Orange", "Moehre", "Banane", "Erdbeeren", "Ananas", "Traube", "Zitrone", "Pfirsich" };

        static void Main(string[] args)
        {
            string[] obstergebnis = Obstfilter();
            foreach (string obst in obstergebnis)
            {
                Console.WriteLine(obst);
            }
            Console.ReadKey();
         }

        static string[] Obstfilter()
        {
            List<string> obstkorbliste = obstkorb.ToList();
            for (int i = obstkorbliste.Count - 1; i >= 0; i--)
            {
                if (obstliste.Contains(obstkorbliste[i]))
                {
                    obstkorbliste.Remove(obstkorbliste[i]);
                }
            }
            return obstkorbliste.ToArray();
        }
    }
05.04.2023 - 18:48 Uhr

Ich denke, du benötigst ein ItemsControl, dass Du an eine Liste bindest.
Der Lagerplatz selbst ist ein Datatemplate, das dem ItemsControl als Template zugewiesen wird.
Im ViewModel gibt es dann eine ObservableCollection<Lagerplatz>.

<ItemsControl x:Name="ItemsControlRegal" 
              Grid.Row="1"
              ItemsSource="{Binding Lagerplaetze}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <UniformGrid x:Name="UniformGridIndices" Rows="5" Columns="6" />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <local:Lagerplatz />
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>
08.02.2023 - 20:30 Uhr

In WPF könnte dies so aussehen:
Pakete CommunityToolkit.Mvvm installieren für das RelayCommand.
Microsoft.Xaml.Behaviors.Wpf installieren für die Eventverarbeitung

Ein MainWindow erstellen, ViewModel (vm) und Behaviors (behav) definieren.
Datenbindung für das Window loaded event und den Text für das Label erstellen.


<Window x:Class="MyCSharp125145.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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:behav="http://schemas.microsoft.com/xaml/behaviors"
        xmlns:vm="clr-namespace:MyCSharp125145.ViewModels"
        mc:Ignorable="d"
        Title="MainWindow" 
        Height="150" 
        Width="250">

    <Window.DataContext>
        <vm:MainWindowViewModel />
    </Window.DataContext>
    
    <behav:Interaction.Triggers>
        <behav:EventTrigger EventName="Loaded">
            <behav:InvokeCommandAction Command="{Binding WindowLoadedEventCommand}" />
        </behav:EventTrigger>
    </behav:Interaction.Triggers>

    
    <Grid>
        <Label x:Name="welcomeLabel"
               Content="{Binding WelcomeLabelText}" />
    </Grid>
</Window>

Wir brauchen auch ein ViewModel, das die Logik des MainWindows enthält. Dieses ist abgeleitet von ViewModelBase


public class MainWindowViewModel : ViewModelBase
    {
		private string welcomeLabelText;

		public string WelcomeLabelText
        {
			get { return welcomeLabelText; }
			set
			{
				if (welcomeLabelText != value)
				{
                    welcomeLabelText = value;
					OnPropertyChanged();
				}
			}
		}

		public ICommand WindowLoadedEventCommand { get; private set; }

		public MainWindowViewModel()
		{
			WindowLoadedEventCommand = new RelayCommand(SetLabelText);
		}

		private void SetLabelText()
		{
            WelcomeLabelText = "Hallo";
        }
	}

    public abstract class ViewModelBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }

28.01.2023 - 19:07 Uhr

Also ich weiß jetzt nicht genau, ob ich das Problem verstanden habe.
Aber wenn im UserControl folgendes steht


<vm IrgendeineViewModelKlasse x:Key="Schluessel"/>

,
dann wird doch für jedes Usercontrol eine eigene Instanz erstellt. Das ist dann nicht das gleiche.

Eine ObservableCollection braucht im Übrigen auch kein PropertyChanged, weil dies bereits in der ObservableCollection implementiert ist.

Folgendes sollte funktionieren.


    public class IrgendeineViewModelKlasse : INotifyPropertyChanged
    {
        public ObservableCollection<IrgendeineKlasseAusDB> Sammlung { get; set; }

        public IrgendeineViewModelKlasse()
        {
            Sammlung = new ObservableCollection<IrgendeineKlasseAusDB>();
        }

        private string neueStation;

        public string NeueStation
        {
            get { return neueStation; }
            set
            {
                if (neueStation != value)
                {
                    neueStation = value;
                    OnPropertyChanged(nameof(NeueStation));
                    if (neueStation.EndsWith('#'))
                    {
                        AddNeueStation();
                    }
                }
            }
        }

        private void AddNeueStation()
        {
            Sammlung.Add(new IrgendeineKlasseAusDB() { Ortsname = NeueStation.TrimEnd('#') });
            NeueStation = string.Empty;
        }

        public event PropertyChangedEventHandler? PropertyChanged;

        protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
        {
            if (PropertyChanged != null)
            {
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }

    public class IrgendeineKlasseAusDB
    {
        public string Ortsname { get; set; }
    }


<UserControl x:Class="MyCSharp125121.StationView"
             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" 
             mc:Ignorable="d">
    
    <Grid>
        <ComboBox ItemsSource="{Binding Sammlung}"
                  DisplayMemberPath="Ortsname" />
    </Grid>
</UserControl>


<Window x:Class="MyCSharp125121.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:MyCSharp125121"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    
    <Window.DataContext>
        <local:IrgendeineViewModelKlasse />
    </Window.DataContext>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>

        <Grid Grid.Column="0">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="*" />
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="*" />
                <RowDefinition Height="*" />
            </Grid.RowDefinitions>
            <local:StationView x:Name="Stationen" 
                               Grid.Column="0"
                               Grid.ColumnSpan="2"
                               Grid.Row="0" />
            <TextBox Grid.Row="1"
                     Grid.Column="0"
                     Grid.ColumnSpan="2"
                     Text="{Binding NeueStation, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
        </Grid>
        <local:StationView x:Name="Strecken" Grid.Column="1" />
    </Grid>
</Window>

Ich weiß, dass ich damit keinen Schönheitspreis gewinnen kann!

24.01.2023 - 09:39 Uhr

Ich nutze doch nur eine Abkürzung um die exe aus zu führen und trotzdem ist ein Workingdir notwendig? Was passiert da im Hintergrund?

Die Antwort hast Du Dir doch im Eingangspost schon selber gegeben! Deine Exe findet doch auch die Dateien nicht selber, wenn sie in einem anderen Ordner als die CMD-Dateien liegt.
Vereinfacht gesagt, ist der Arbeitsordner immer der Ordner, in dem das Programm gestartet wird, wenn nichts anderes angegeben wird. In Deinem Fall mit der Verknüpfung wird das Programm halt dann wahrscheinlich vom Desktop getsartet und der Arbeitsordner ist eben der Desktop.

22.01.2023 - 22:17 Uhr

Erstelle ein ViewModel


public class MainWindowViewModel
    {
        public ObservableCollection<Auto> AutoListe { get; set; }

        public MainWindowViewModel()
        {
            AutoListe = new ObservableCollection<Auto>()
            {
                new Auto() { Marke = "Audi", Modell = "R8", PS = 610, Logo = "Images/logo_audi.jpg" },
                new Auto() { Marke = "Bentley", Modell = "CS", PS = 630, Logo = "Images/logo_bentley.jpg" },
                new Auto() { Marke = "Lambo", Modell = "LP 700", PS = 700, Logo = "Images/logo_lambo.jpg" },
                new Auto() { Marke = "SEAT", Modell = "DSG", PS = 300, Logo = "Images/logo_seat.jpg" },
                new Auto() { Marke = "Skoda", Modell = "RS", PS = 230, Logo = "Images/logo_skoda.jpg" },
                new Auto() { Marke = "VW", Modell = "TDI 8", PS = 240, Logo = "Images/logo_vw.jpg" }
            };
        }
    }

Erstelle eine Instanz des Viemodels in der View und definiere die Listbox. Das Datatemplate muss nach den Bedürfnissen angepasst werden.


<Window x:Class="MyCSharp125114.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:MyCSharp125114"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    
    <Window.DataContext>
        <local:MainWindowViewModel />
    </Window.DataContext>
    
    <Grid>
        <ListBox Name="MyListBox"  Margin="10" ItemsSource="{Binding AutoListe}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <Image Source="{Binding Logo}" />
                        <TextBlock Margin="10, 0" Text="{Binding Marke}" />
                        <TextBlock Text="{Binding Modell}" />
                        <TextBlock Margin="10, 0" Text="{Binding PS}" />
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>
</Window>

19.09.2022 - 22:43 Uhr

Das break in der for-Schleife sorgt dafür, dass die Schleife bereits beim ersten Durchlauf verlassen wird.

20.08.2022 - 23:14 Uhr

Servus,

lassen sich eigentlich die Beiden ComboBoxen (Prjektmappenkonfiguration und Projektmappenplattform) in Visual Studio in der Breite anpassen?

25.06.2022 - 23:31 Uhr

Geht doch! Da fehlt nur eine Klammer und statt einem Komma braucht man ein Semikolon.


try
{
    using (wr = new StreamWriter(dateiname))
        for (int zl = 0; zl < breite; ++zl)
        {
            for (int sp = 0; sp < breite; ++sp)
            {
                int dist = breite - zl;
                //if ((zl - sp) % 5 == 0)
                //{
                //    wr.Write('+');
                //}
                //else
                //{
                //    wr.Write('_');
                //}
                wr.Write((zl - sp) % 5 == 0 ? '+' : '_');
            }
            wr.WriteLine();
        }
}


25.06.2022 - 00:36 Uhr

Also ich würde es wahrscheinlich mit einer Regenechse machen.
Es wird sich ja wahrscheinlich nur der Teil nach dem ? ändern.

28.05.2022 - 00:55 Uhr

Ich mache das mit dem Nuget-Paket Microsoft.Xaml.Behaviors.Wpf.


<Window x:Class="CSharp124655.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:CSharp124655"
        xmlns:behav="http://schemas.microsoft.com/xaml/behaviors"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">

    <Window.Resources>
        <DataTemplate x:Key="AddressTemplate" DataType="{x:Type local:AddressViewModel}">
            <Border BorderThickness="2"
                    BorderBrush="Black"
                    CornerRadius="3"
                    Padding="3">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="auto" />
                    <RowDefinition Height="auto" />
                    <RowDefinition Height="auto" />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="10" />
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>
                <TextBlock Grid.Row="0"
                           Grid.Column="0">
                    <Run Text="ID: " />
                    <Run Text="{Binding Id}" />
                </TextBlock>
                <TextBlock Grid.Row="1"
                           Grid.Column="0">
                    <Run Text="StockName: " />
                    <Run Text="{Binding StockName}" />
                </TextBlock>
                <TextBlock Grid.Row="2"
                           Grid.Column="0">
                    <Run Text="City: " />
                    <Run Text="{Binding City}" />
                </TextBlock>
                <TextBlock Grid.Row="0"
                           Grid.Column="2">
                    <Run Text="Postal code: " />
                    <Run Text="{Binding Postcode}" />
                </TextBlock>
                <TextBlock Grid.Row="1"
                           Grid.Column="2">
                    <Run Text="Street: " />
                    <Run Text="{Binding Street}" />
                </TextBlock>
                <TextBlock Grid.Row="2"
                           Grid.Column="2">
                    <Run Text="HouseNumber: " />
                    <Run Text="{Binding HouseNumber}" />
                </TextBlock>
            </Grid>
            </Border>
        </DataTemplate>
    </Window.Resources>

    <Window.DataContext>
        <local:MainWindowViewModel x:Name="DataContext" />
    </Window.DataContext>
    
    <Grid>
        <ListBox x:Name="AddressesListBox"
                 ItemsSource="{Binding Addresses}"
                 SelectedItem="{Binding SelectedAddress}"
                 SelectionMode="Single" 
                 ItemTemplate="{StaticResource AddressTemplate}">
            <behav:Interaction.Triggers>
                <behav:EventTrigger EventName="SelectionChanged">
                    <behav:InvokeCommandAction Command="{Binding OnSelectionChanged}" />
                </behav:EventTrigger>
            </behav:Interaction.Triggers>
        </ListBox>

    </Grid>
</Window>


using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Windows.Input;

namespace CSharp124655
{
    public class MainWindowViewModel : ViewModelBase
    {
        public ObservableCollection<AddressViewModel> Addresses { get; private set; }

        public AddressViewModel SelectedAddress { get; set; }

        public ICommand OnSelectionChanged { get; private set; }

        public MainWindowViewModel()
        {
            Addresses = new ObservableCollection<AddressViewModel>();
            for (int i = 1; i < 6; i++)
            {
                Addresses.Add(new AddressViewModel() { City = $"City{i}", HouseNumber = i, Id = i + 10000, Postcode = $"12340{i}", StockName = $"Name{i}", Street = $"Street{i}" });
            }

            OnSelectionChanged = new RelayCommand(o => { ContinueWithSelectedItem(); });
        }

        private void ContinueWithSelectedItem()
        {
            Debug.WriteLine(SelectedAddress.StockName);
        }
    }
}

06.03.2022 - 14:27 Uhr

Falls Dein Projekt .Net5/6 ist, dann einfach in der Projektdatei (.csproj) WindowsForms aktivieren.


<UseWindowsForms>true</UseWindowsForms>

Danach kannst Du den FolderBrowserDialog aufrufen.


System.Windows.Forms.FolderBrowserDialog folderBrowsingDialog = new System.Windows.Forms.FolderBrowserDialog

Es ist eigentlich kein Gefrickel mit COM notwendig!

28.01.2022 - 20:24 Uhr

You will own nothing and you will be happy!

26.01.2022 - 10:27 Uhr

Kann mir bitte jemand helfen?

Ich bekomme den Fehler: "The JSON value could not be converted to System.String. Path: $.success | LineNumber: 0 | BytePositionInLine: 15."
Bei diesem Code:

  
public class Mitarbeiter  
    {  
        public string success { get; set; }  
        public Data data { get; set; }  
    }  
  

Ändere die Mitarbeiterklasse wie folgt:


public class Mitarbeiter
    {
        public bool success { get; set; }
        public Data data { get; set; }
    }

14.01.2022 - 19:36 Uhr

@Caveman das sieht nach .NET 3.5 Code oder früher aus.
Seit .NET 4 kann man einfach CopyTo verwenden

Ich habe in dem Fall einfach nur stur gegoogelt und die erstbesten Beispiele von StackOverflow kopiert.
Dass mit CopyTo habe ich gelesen, wollte es aber nicht posten, weil es dann keine 5 Zeilen Code geworden wären 😉

Deswegen hatte ich auch geschrieben, dass ich das selber nicht probiert hatte.

14.01.2022 - 01:15 Uhr

Ein Bild in den Speicher laden


using (MemoryStream ms = new MemoryStream())
using (FileStream file = new FileStream("file.bin", FileMode.Open, FileAccess.Read)) {
   byte[] bytes = new byte[file.Length];
   file.Read(bytes, 0, (int)file.Length);
   ms.Write(bytes, 0, (int)file.Length);
}

Im View Model eine Eigenschaft vom Typ byte[] anlegen


private byte[] userImage;

public byte[] UserImage
   {
       get { return userImage; }
       set
       {
           if (value != userImage)
           {
               userImage = value;
               OnPropertyChanged("UserImage");
           }
       }
   }

Und im Xaml darauf binden


<Image Source="{Binding UserImage}"/>

Alles ungetestet! Das Byte-Array muss noch mit der Eigenschaft UserImage verbunden werden.

06.01.2022 - 16:33 Uhr

Ich habe auf Github eine zweite Version veröffentlicht.

In dieser Version wird ein "Navigator" zum Umschalten der ViewModels verwendet.

MainView:


<Window x:Class="Forum124378II.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:Forum124378II"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="300">

    <Window.Resources>
        <DataTemplate DataType="{x:Type local:CustomerViewModel}">
            <local:Customers />
        </DataTemplate>
        <DataTemplate DataType="{x:Type local:DealerViewModel}">
            <local:Dealers />
        </DataTemplate>
    </Window.Resources>
    
    <Window.DataContext>
        <local:MainWindowViewModel />
    </Window.DataContext>

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="auto" />
            <RowDefinition Height="*" />
            <RowDefinition Height="60" />
        </Grid.RowDefinitions>

        <StackPanel Grid.Row="0"
                    Orientation="Horizontal"
                    HorizontalAlignment="Center">
            <TextBlock Text="Views: "
                       VerticalAlignment="Center"/>
            <ComboBox ItemsSource="{Binding ViewTypes}"
                      SelectedItem="{Binding SelectedViewType}"/>

        </StackPanel>

        <ContentControl Grid.Row="1"
                        HorizontalAlignment="Stretch"
                        Content="{Binding CurrentViewModel}" />

        <TextBlock Grid.Row="2"
                   FontWeight="Bold"
                   Foreground="Red">
            <Run Text="Error: " />
            <Run Text="{Binding ErrorMessage}" />
        </TextBlock>
                   
    </Grid>
</Window>

MainViewModel


using System;
using System.Collections.Generic;
using System.Linq;

namespace Forum124378II
{
    public class MainWindowViewModel : ViewModelBase
    {
        private Navigator navigator;
        private ViewModelFactory viewModelFactory;
        private ViewModelTypes selectedViewType;
        private string errorMessage;

        public ViewModelBase CurrentViewModel
        {
            get { return navigator.CurrentViewModel; }
        }

        public string ErrorMessage
        {
            get { return errorMessage; }
            set
            {
                if (errorMessage != value)
                {
                    errorMessage = value;
                    OnPropertyChanged();
                }
            }
        }

        public IEnumerable<ViewModelTypes> ViewTypes
        {
            get
            {
                return Enum.GetValues(typeof(ViewModelTypes)).Cast<ViewModelTypes>();
            }
        }

        public ViewModelTypes SelectedViewType
        {
            get { return selectedViewType; }
            set
            {
                if (selectedViewType != value)
                {
                    selectedViewType = value;
                    OnPropertyChanged();
                    UpdateView();
                }
            }
        }

        public MainWindowViewModel()
        {
            navigator = new Navigator();
            viewModelFactory = new ViewModelFactory();

            navigator.StateChanged += ViewModelChanged;
            SelectedViewType = ViewModelTypes.Customers;
            navigator.CurrentViewModel = viewModelFactory.Get(SelectedViewType);
        }

        private void UpdateView()
        {
            navigator.CurrentViewModel = viewModelFactory.Get(SelectedViewType);
        }

        private void ViewModelChanged()
        {
            OnPropertyChanged(nameof(CurrentViewModel));
            if (CurrentViewModel is IMessage viewModelWithMessage)
            {
                ErrorMessage = viewModelWithMessage.Message;
            }
        }
    }
}

Navigator:


using System;

namespace Forum124378II
{
    public class Navigator
    {
        private ViewModelBase currentViewModel;

        public ViewModelBase CurrentViewModel
        {
            get
            {
                return currentViewModel;
            }
            set
            {
                currentViewModel = value;
                StateChanged?.Invoke();
            }
        }

        public event Action StateChanged;
    }
}

Wenn der Navigator ein neues ViewModel erhält, dann wird ein Event gefeuert.
Das MainViewModel hat dieses Event aboniert und reagiert darauf mit der Methode ViewModelChanged.
In der Methode wird die Eigenschaft CurrentViewModel aktualisiert, was einen Austausch des DataTemplates in der View zur Folge hat.
Weiterhin wird geprüft, ob das ViewModel die Schnittstelle IMessage implementiert.
Falls dem so ist, dann wird der Wert aus der Eigenschaft Message im CurrentViewModel in die Eigenschaft ErrorMessage geschrieben.

04.01.2022 - 19:24 Uhr

Servus,

ganz kann ich dem Code im Eingangspost nicht folgen.
Deshalb eine Eigenkreation, die vielleicht das gewünschte berwerkstelligt.
Wie von Th69 schon angemerkt, solltest Du eine Basisklasse für Deine ViewModels haben:


public class ViewModelBase : INotifyPropertyChanged
    {
        #region INotifyPropertyChanged_Implementation
        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
        #endregion
    }

Von dieser Basisklasse leiten die folgenden zwei Klassen ab:


    public class CustomerViewModel : ViewModelBase, IViewModelWithMessage
    {
        public string Message { get; private set; }

        public CustomerViewModel(int i)
        {
            Message = $"Customer {i} is greeting you!";
        }
    }



public class NonCustomerViewModel : ViewModelBase
    {
        public NonCustomerViewModel()
        {
            
        }
    }

Die CustomerViewModel Klasse implementiert auch das Interface für das Message-Property


public interface IViewModelWithMessage
    {
        string Message { get; }
    }

Erzeugt werden die konkreten Klassen im MainWindowViewModel


public class MainWindowViewModel : ViewModelBase
    {
        public int Index { get; set; }

        public List<ViewModelBase> ViewModels { get; set; }

        private string newMessage;

        public string NewMessage
        {
            get { return newMessage; }
            set
            {
                if (newMessage != value)
                {
                    newMessage = value;
                    OnPropertyChanged();
                }
            }
        }

        public ICommand MoveToNextViewModelCmd { get; }

        public MainWindowViewModel()
        {
            Index = 0;
            ViewModels = new List<ViewModelBase>();
            for (int i = 0; i < 2; i++)
            {
                ViewModels.Add(new CustomerViewModel(i));
            }
            for (int i = 0; i < 3; i++)
            {
                ViewModels.Add(new NonCustomerViewModel());
            }
            for (int i = 5; i < 10; i++)
            {
                ViewModels.Add(new CustomerViewModel(i));
            }
            MoveToNextViewModelCmd = new MoveToNextViewModelCommand(this);
        }
    }

Das zugehörige MainWindow


<Window x:Class="Forum.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:Forum"
        mc:Ignorable="d"
        Title="MainWindow">

    <Window.DataContext>
        <local:MainWindowViewModel />
    </Window.DataContext>
    
    <StackPanel HorizontalAlignment="Center">
        <Button Content="Next" Command="{Binding MoveToNextViewModelCmd}" />
        <Label>Meldung:</Label>
        <TextBlock x:Name="txtMessage" Text="{Binding NewMessage}"/>
    </StackPanel>
</Window>

Beim Drücken auf den Button in der Mainview wird in der Kommando-Klasse der Text aus der Customer-Klasse in das MainWindowViewModel übertragen.


internal class MoveToNextViewModelCommand : ICommand
    {
        public event EventHandler? CanExecuteChanged;

        private ViewModelBase viewModel;

        public MoveToNextViewModelCommand(ViewModelBase anyViewModel)
        {
            viewModel = anyViewModel;
        }

        public bool CanExecute(object? parameter)
        {
            return true;
        }

        public void Execute(object? parameter)
        {
            if (viewModel is MainWindowViewModel mainViewModel)
            {
                if (mainViewModel.Index == mainViewModel.ViewModels.Count)
                {
                    mainViewModel.Index = 0;
                }
                if (mainViewModel.ViewModels[mainViewModel.Index] is IViewModelWithMessage viewModelWithMessage)
                {
                    mainViewModel.NewMessage = viewModelWithMessage.Message;
                }
                else
                {
                    mainViewModel.NewMessage = $"ViewModel at Index { mainViewModel.Index } is of type { mainViewModel.ViewModels[mainViewModel.Index] } and has therefore no Message-Property";
                }
                mainViewModel.Index++;
            }
        }
    }

Ich habe den Quellcode auch auf Github

01.01.2022 - 22:33 Uhr

Also das MS Exchange scheint ein einziger großer Bug zu sein. Was da alles hochkommt.
Das neueste: 2022-Bug

01.01.2022 - 18:06 Uhr

Ich persönlich habe noch nie eine "Generic.xaml" genutzt 😁
Also wenn es für diesen speziellen Namen irgendwelche Sonderregelungen gibt, weiß ich nichts davon.

Diese zwei Sätze haben mir die Augen geöffnet, auch wenn wir da aneinander vorbei reden. Ich bin so ein Dödel. Hat mich jetzt keine 30 Minuten gekostet, das Projekt ans Laufen zu bekommen! Gestern ist mir das nach 10 Stunden Google-Suche und etlichen Gläsern Bowle nicht eingefallen.
Lösung: Der richtige Projekttyp ist wichtig. Statt "WPF-Klassenbibliothek" hätte ich "Bibliothek benutzerdefinierter WPF-Steuerelemente" auswählen müssen. Dann wird nämlich auch der Themes-Ordner mit Generic.xaml angelegt und verwendet!

Vielen Dank @Palladin007!

01.01.2022 - 15:59 Uhr

Hallo,
ich habe begonnen, meine Controls unter Visual Studio 2022 aud .Net6 umzustellen. Dafür verwende ich ein eigenes Projekt (nur der Übung halber!).
Wie ich nun feststellen muss, wird der zum Control definierte Style aus der Generic.xaml nicht zugewiesen, so dass das komplette Control nicht sichtbar wird.
Google sagt, dass das früher schon immer mal ein Problem war und dass das an einem doppelten Generic.xaml liegen könnte. Die vorgeschlagenen Lösungen habe ich erfolglos durchprobiert. Wenn ich den kompletten Style im instantierten Control zuweise funktioniert alles.
Die Generic.xaml besteht nur aus einem ResourceDictionary, wo auf die xaml-Dateien für die einzelnen Controls verwiesen wird.

Hat hier jemand einen Tip?

28.11.2021 - 14:36 Uhr

Servus,

am einfachsten scheint mir das unter Verwendung des NuGet-Paketes CoreAudio realisierbar zu sein.
https://docs.microsoft.com/en-us/windows/win32/api/_coreaudio/ Die Dokumentation zur CoreAudioApi

Ein auf die Schnelle hingeschmierter Code:


using System;
using CoreAudio;

namespace AudioCore
{
    internal class Program
    {
        static MMDeviceCollection speakerList;
        static MMDevice activeSpeaker;


        static void Main(string[] args)
        {
            MMDeviceEnumerator deviceEnumerator = new();
            speakerList = deviceEnumerator.EnumerateAudioEndPoints(EDataFlow.eRender, DEVICE_STATE.DEVICE_STATE_ACTIVE);
            activeSpeaker = deviceEnumerator.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia);

            foreach (MMDevice device in speakerList)
            {
                Console.WriteLine(device.FriendlyName);
                Console.WriteLine(device.ID);
                Console.WriteLine("--");
            }

            SetDefaultAudioDevice();

            Console.ReadKey();
        }

        static void SetDefaultAudioDevice()
        {
            MMDeviceEnumerator deviceEnumerator = new();
            foreach (MMDevice device in speakerList)
            {
                if (!device.ID.Equals(activeSpeaker.ID))
                {
                    deviceEnumerator.SetDefaultAudioEndpoint(device);
                    break;
                }
            }
        }
    }
}

22.08.2021 - 21:05 Uhr

Ich vermute mal, dass die Bindungen dadurch zustande kommen, weil Du den DataContext vom DataTemplate direkt auf das ToolViewModel bindest. Wie Papst schon angemerkt hat, fehlt das Tools-Property im ViewModel.

In Deinem ViewModel musst Du ein Property Tools vom Typ List<ToolViewModel> definieren. Du brauchst in dem Fall keine ObservableCollection<ToolViewModel>, da sich die Anzahl der Tools nicht ändert.
Das DataTemplate ToolChangeView änderst Du wie folgt.


        <DataTemplate DataType="{x:Type local:ToolViewModel}">
            <views:ToolChangeView />
        </DataTemplate>

Du solltest auch überlegen, ob Du das ToolViewModel nicht verallgemeinern kannst. Tooldate und Basedaten haben beim KUKA die gleiche Struktur.

Hier nochmals als Code:


        <ListView x:Name="lstNewTool" 
                  ItemsSource="{Binding Tools}" 
                  ScrollViewer.HorizontalScrollBarVisibility="Disabled" 
                  ScrollViewer.VerticalScrollBarVisibility="Auto" 
                  SelectionMode="Single" 
                  Margin="5" 
                  Width="400">
            <ListView.ItemTemplate>
                <DataTemplate DataType="{x:Type local:ToolViewModel}">
                    <StackPanel>
                        <TextBlock Text="{Binding ToolName}" />
                        <TextBlock Text="{Binding ToolNumber}" />
                        <TextBlock Text="{Binding ToolData.X}" />
                        <TextBlock Text="{Binding ToolData.Y}" />
                    </StackPanel>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>


    public class MainWindowViewModel : ViewModelBase
    {
        public ObservableCollection<ToolViewModel> Tools { get; set; }

        public MainWindowViewModel()
        {
            Tools = new ObservableCollection<ToolViewModel>
            {
                new ToolViewModel()
            };
        }
    }

12.07.2021 - 21:08 Uhr

Das
>
mit "with leading white space" hat dann immerhin ein Ergebnis gegeben, aber nicht, das, was ich mir erhofft habe. Umwandeln klappte natürlich damit erst recht nicht.

  
22.06.2021 00:00:00 +00:00  
  
  
                    string stringDate = managementObject["InstalledOn"].ToString();  
                    string format = "M/dd/yyyy"; // M/d/yyyy geht auch  
                    CultureInfo provider = CultureInfo.InvariantCulture;  
                    DateTimeOffset result = new DateTimeOffset();  
                    result = DateTimeOffset.ParseExact(stringDate, format, provider, DateTimeStyles.AssumeUniversal);  
                    systemLastWindowsUpdate = result.ToString();  
  

Und wenn Du die letzte Zeile wie folgt schreibst?


systemLastWindowsUpdate = result.ToString("yyyy-MM-dd");