Laden...

Profil von lutzeslife

myCSharp.de - Member Mitglied seit

Alle Beiträge

24.11.2025 - 09:21 Uhr

Microsoft passt aktuell immer wieder Schnittstellen im COM Model an. Das Problem dabei ist das schnell mal zwischen zwei Office Versionen gleichen Majorversionen eine Automation API nicht funktioniert. Wenn du neuere Versionen nicht brauchst fährt man am besten eine ältere Version der Library zu referenzieren und mitzuliefern z.B. die 15 Versionen aus Office 2013.

Wie Abt bereits geschrieben hat sind seid Office 2016 die Versionen nicht mehr aussagekräftig hinsichtlich der Hauptversion und via API hat sich die Version 16.**** nicht mehr geändert. Der einzige Weg eine vernünftige Versionsnummer zu bekommen ist via Registryauswertung über API bekommst du je nach verwendeter App mal mehr mal weniger Infos.

P.S. Microsoft liefert seid einiger Zeit auch keine aktualiserten Interop Bibliotheken aus. Wenn du immer die neusten brauchen solltest musst du die Typdefinitionen die mit dem VBA Editor von Office ausgeliefert nutzen um eine .net Bibliothek zu erstellen, die funktionieren aber nur für diese Office Version und später.

03.09.2025 - 10:53 Uhr
var element = gltModbusPVPlainNode
        		.Element(ns + "addData")
        		.Element(ns + "data")
        		.Element(ns + "InterfaceAsPlainText")

Du kannst zunächst das Element in eine Variable schieben und was spricht dagegen den Namespace im Anschluss per Add ein neues Attribut hinzuzufügen?

XNamespace ns = "[NAMESPACE]";
element.Add(new XAttribute(ns));
12.08.2025 - 08:56 Uhr

Wenn du es besser trennen willst, die RibbonGalleryhat ein SelectionChanged Event. Mittels EventToCommand Behaviour könntest du im ViewModel die Property umschalten die dei Command.CanExecute für den Speichern-Button steuert.

11.08.2025 - 15:47 Uhr

Für was brauchst du ein Selection Event. Du bindest an SelectionBoxItem Property der ComboBox. Die Property wird wenn der Nutzer ein anderen Wert auswählt automatisch bei richtigem Binding aktualisiert.

Dann kannst du weiter machen.

Du setzt auch jedes Mal das Dokument zurück, da wäre die Frage ob das korrekt erfolgt. Für deinen Anwendungsfall könntest du auch überlegen das DOkument ungespeichert zu schließen und erneut aufzumachen. Dann brauchst du es nicht wieder zurücksetzen.

Da du mit einer Vorlage schon arbeitest könntest du mittels SaveAs deine Änderung temporär in ein docx speichern und nach dem schließen des DOkumentes dieses löschen, das erspart das erneute ersetzen.

Falls dein Dokument sehr umfangreich ist könnte man auch überlegen ob man die Stellen die man ersetzen möchte anstelle von Search&Replace die Stellen in ContentControl setzt und dann nur den Inhalt der ContentControls ersetzt, das wäre etwas stabiler.

Du convertierst immer noch rum und arbeitest nicht mit den Methoden:

// Bisher
int year = dateTimePicker.Value.Year;
int month = dateTimePicker.Value.Month;
int day = dateTimePicker.Value.Day;

// Neu
DateTime startDate = dateTimePicker.Value;

dann

 // Bisher
 DateTime endDate = new DateTime(year, month + Convert.ToInt32(Seiten), day); //Seiten=Anzahl der Monate
 
 // Neu
 endDate = startDate.AddMonths(Seiten);

dann kannst du

// Bisher
int Seiten = Convert.ToInt16(txtbxAnzahl.Text);

// Neu
int Seiten = Convert.ToInt32(txtbxAnzahl.Text);

Der Typ int selber ist ein Wrapper der wählt auf dem System die Variante entsprechend aus. Außerdem musst du nicht hin unher konvertieren zwischen int16 und int32

Dann

dateTimePicker.Value = DateTime.Parse(lastDayOfMonth.ToString("dd MMMM yyyy"));
replaceDate = dateTimePicker.Text;

Du brauchst nicht den Weg über den DateTimePickergehen. Du konvertiesert deine Berehcnung ja zu einem String das Format ist frei wählbar da kannst für replacedDate gleich das entsprechende String erstellen und du sparst dir das Parsing.

Und dann gehst du immer noch unsauber mit den COM Objekten der API um. Immer und ich meine immer wenn du ein Objekt der API abrufst das eine Reference und kein Value ist muss und damit meine ich wirklich muss das Objekt auch wieder freigegeben werden.

Beispiel

wordApp = new Word.Application(); // muss freigegebn werden
doc = wordApp.Documents.Open // hier erfolgt ein Abruf des Documents Object das gar nicht freigegeben wird und natürlich Document selber das von Open geliefert wird

weiter unten dann Selection, Find usw.

Für die Lesbarkeit bitte

  • auskommentierten Code löschen, deswegen gibt es Versionsverwaltung wie git
  • keine Variablen deklarieren     TimeSpan time2 = new TimeSpan(800); die nicht gebraucht werden.

Bevor wir zum eigentlichen Problem kommen, bitte die Konvertierungen zu String vermeiden

  string replaceDate = dateTimePicker.Value.ToString();
    int year = Convert.ToInt32(replaceDate.Substring(6,4));
    int month = Convert.ToInt32(replaceDate.Substring(3,2));
    int day = Convert.ToInt32(replaceDate.Substring(0, 2));

DateTimePicker.Value hat als Objekttyp das DateTime das über Properties für Day, Month Year verfügt. Damit kannst du dir also das startDateschon erzeugen. Außerdem kannst du das endDateerzeugen mit startDate.AddMonth(2) und bekommst das neue DateTime. Bitte hier schauen was das Framework liefert.

Die Schleife sieht auch merkwürdig aus:

    for (DateTime date = startDate; date <= endDate; date = date.AddMonths(1))
    {
        // Berechne den letzten Tag des aktuellen Monats
        DateTime lastDayOfMonth = new DateTime(date.Year, date.Month, DateTime.DaysInMonth(date.Year, date.Month));
        MessageBox.Show(lastDayOfMonth.ToString("dd.MMMM yyyy"));
        dateTimePicker.Value = lastDayOfMonth;
        temporarydate = Convert.ToString(dateTimePicker.Value.ToString("dd.MMMM yyyy"));
        ReplaceTextInWordDocument3(filePath, searchString, replaceString, searchDate, temporarydate, Seiten);

    }

Die doppelte Konvertierung zu stringConvert.ToString(dateTimePicker.Value.ToString("dd.MMMM yyyy"))kann mann sich sparen, warum willst du den Wert dem DateTimePicker  zu ordnen?  usw.

Ich würde da erstmal aufräumen und anschließend die genaue Fehlermeldung posten ggf. auch im Netz danaach suchen sonst ist das das nur raten. Und was genau wird in Replace gemacht und wo tritt die Meldung auf.

Fast alles was du in VBA machen kannst kannst du auch über die C# Schnittstelle machen, ich würde da nichts mixen.

Okay vielleicht mal schauen welcher Process den Dialog aufmacht, eventuell kann man über Automation den Dialog ansteuern und bestätigen

Kann denn der Drucker randlos drucken? Wenn ja vielleicht mal als Standard im Drucker hinterlegen dass es unterstützt wird. Wenn der Drucker den Dialog erzwing wirst du nicht viel machen können.

Wenn jetzt in Word steht es wird gedruckt und es passietr nichts, dann kann es sein, dass der Drucker (ist der Standarddrucker verfügbar) nicht verfügbar ist, eine manuelle Eingabe erforderlich ist usw. Druckt er wenn du über VBA es versuchst. Word API ist vergleichsweise alt, ggf. den Umweg über PDF erzeugen und das dann drucken gehen.

Du kannst versuchen mit Application.DisplayAlerts die Meldung zu unterdrücken. Vielleicht als Tipp auch, wenn du öfters mit Word API arbeitest, es handelt sich dabei um COM Objekte, die sollten aus Erfahrung vernünftig  freigegeben werden.

Sollte des nicht mit NavigationStarting umsetzbar sein (Quelle). Der Nutzer klickt auf den Link, du  redirectest die URL oder brichst ab oder was auch immer.

05.06.2025 - 09:13 Uhr

Leider ist es auf den Screenshot nicht zu erkennen, aber wenn das Custom Tool dort korrekt gesetzt ist wird die Resources.Designer.cs auch entsprechend erstellt, so sieht es zumindestens auch auf dem Screenshot bei dir aus da ein Expander File neben der Resx ist. Dann kannst du per Angabe auch darauf zugreifen.

Wennn deine *.resx im gleichen Namespace liegt wie die Klasse in der du sie verwendest musst du kein Namespace angeben, liegt sie in einem anderen Ordner dann muss der Namespace angegeben werden. Intellisense sollte dir das auch korrekt vorschlagen.

Falls es nur um den Fortschritt geht wäre auch IProgress<T> etwas.

03.06.2025 - 13:37 Uhr

Viel zu kompliziert,

  1. Kontextmenü auf Resources.resx
    1. Build Action = Embedded Resource
    2. Custom Tool = ResXFileCodeGenerator
  2. Kompilieren

nun kannst du via [Namespace].Properties.Resource.[Name] direkt via C# darauf zugreifen.

19.05.2025 - 09:06 Uhr

Super danke, auf die Idee bin ich gar nicht gekommen 🤦‍♂️, das funktioniert prima.

16.05.2025 - 10:26 Uhr

Hallo Community,

ich versuche gerade eine Art InlineEditor zu bauen. In einem Template für ein ListBoxItem habe ich ein ContentControl das per Trigger zwischen einem TextBlock und einer TextBox für eine string Property wechselt:

<ContentControl x:Name="nameContent" Style="{StaticResource DefaultContentControlStyle}" DataContext="{Binding RelativeSource={RelativeSource Mode=Self}, Path=DataContext}" Grid.Column="3" Template="{StaticResource ShowNameTemplate}">
    <xamlBehaviours:Interaction.Triggers>
        <xamlBehaviours:EventTrigger EventName="MouseDown" SourceObject="{Binding ElementName=nameContent}">
            <xamlBehaviours:ChangePropertyAction TargetObject="{Binding ElementName=nameContent}" PropertyName="Template" Value="{StaticResource EditNameTemplate}"/>
        </xamlBehaviours:EventTrigger>
        <xamlBehaviours:DataTrigger Value="False" Comparison="Equal" Binding="{Binding RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}, Path=IsSelected}">
            <xamlBehaviours:ChangePropertyAction TargetObject="{Binding ElementName=nameContent}" PropertyName="Template" Value="{StaticResource ShowNameTemplate}" />
        </xamlBehaviours:DataTrigger>
    </xamlBehaviours:Interaction.Triggers>
</ContentControl>

Das funktioniert soweit auch gut. Was noch nicht funktioniert ist das Setzen des Fokus wenn die TextBox aktiviert wird.  Durch das MouseDownwird ja ein Fokus gesetzt, scheinbar kann ich nicht gleichzeitig wenn die TextBox geladen wird den Fokus erneut setzen, dass hatte ich mit einem weiteren Trigger versucht:

  • wenn TextBox.Loaded
  • wenn TextBox.IsVisible

dann den Fokus zu setzen durch:

  • FocusManager.FocusElement der TextBox
  • TextBox.Focuscall.

Vielleicht hat ja jemand noch eine Idee.

Grüße

Man kan über mehre Spalten sortieren im klassischen Sinn. Man gibt einfach die Property an von dem Model das im DataContext liegt. Das ist auch gar nicht das Problem sondern das SortDescription ein struct ist an deren Propertyan die nicht gebunden werden kann.

YourListView = CollectionViewSource.GetDefaultView(tempListView
.OrderBy(x => x.FirstSorting)
.ThenBy(y => y.SecondSorting));

Das ist etwas anders hier erzeugt du zunächst ein neu Selektion die dann dem View übergeben wird.

Ich habe es jetzt anders gelöst. Ich erzeuge die CollectionViewSource nun im XAML und gruppiere und Sortiere nach anderen Parametern. Über den VisualTree als auch (ListCollectionView)ListBox.ItemsSource komme ich ans View und damit an die erzeugten Gruppen und deren Sortierung damit arbeite ich dann weiter.

Ja das hatte ich mir angeschaut, aber da ist keine Bindung möglich um mehre Inputparameter zu berücksichtigen. Daher muss ich es jetzt anders lösen und das Datenmodell diesbezüglich aufbohren

Hallo Community,

ich versuche eine Art mehrstufige Sortierung bei einer ListBox in WPF hinzubekommen. Dazu folgendes Beispiel (ich verichte auf die ganzen PropertyChanges etc. aufrufe der Übersichtlichkeit halber)

public class Data
{
 public string Name,
 public string Category
 public int Index // das ist der Index aus der Quelle von dem die Daten kommen, dieser kann mehrfach herkommen
 public int Offset
}

Ich habe eine ObservableCollection<Data> die habe ich an eine CollectionViewSource gebunden und die wieder rum an die Listbox.  Über

<PropertyGroupDescription Converter="{StaticResource dataToGroupConverter}" CustomSort="{StaticResource GroupComparer}"/> 

Habe ich einen Converter der die Category zu einer GruppenID macht und der Comparer sortiert die Gruppen dann entsprechend nach. Es gibt noch TemplateSelektoren die ja nach GruppenID ein anderen Style laden aber das spielt gar nicht so eine Rolle.

Vereinfacht wird dann im ListBox folgendes angezeigt:

- Category 1
	- "[Name]" // Instance OBJ 1 hat dann Index 0
	- "[Name]" // Instance OBJ 2 hat Index 3
- Category 2
	- "[Name]" // Instance OBJ 3 hat dann Index 1
	- "[Name]" // Instance OBJ 4 hat dann Index 2
- Category 3
	- "[Name]" // Instance OBJ 5 hat dann Index 1
	- "[Name]" // Instance OBJ 6 hat dann Index 3

Im Moment habe ich eine Problem mit der Sortierung innerhalb einer Gruppe. Die ist aktuell der Reihenfolge wie sie hinzugefügt wurde zur Collection.  Was ich jetzt bräuchte das ist eine Arte zweite Sortierung in Abhängigkeit der ersten Sortierung. D.h.

Im ersten Schritt sortiere ich alle Mitglieder  einer Kategory nach dem Index dann kommt das Beispiel oberen aus. Nun habe ich eine Offset Wert der sagt das mein Position verschoben werden kann (am Beispiel)

// Nach erster Sortierung

- "Kategory 1"
	- "Wert 1" 	// Obj: Name = "Wert 1", Category = "Kategory 1", Index  = 0, Offset = 0
	- "Wert 1" 	// Obj: Name = "Wert 2", Category = "Kategory 1", Index  = 3, Offset = 0
	- "Wert 2"  // Obj: Name = "Wert 3", Category = "Kategory 1", Index  = 4, Offset = -2
	
// Nach zweiter Sortierung

- "Kategory 1"
	- "Wert 2"  // Obj: Name = "Wert 3", Category = "Kategory 1", Index  = 4, Offset = -2
	- "Wert 1" 	// Obj: Name = "Wert 1", Category = "Kategory 1", Index  = 0, Offset = 0
	- "Wert 1" 	// Obj: Name = "Wert 2", Category = "Kategory 1", Index  = 3, Offset = 0

Ich verschiebe also visuell durch den Offset Wert meine Position innerhalb der Gruppe.

Meine erste Idee war die SortDescriptions bzw. CollectionViewSource im Code-behind zu ListCollectionView zu casten und CustomSort zu nutzen. Das wird aber auf alle Elemente der ItemsSource angewandt. Da kenn ich ich als den "GruppenIndex"  noch nicht. Eine weitere Idee war eine zweite sortierte Liste mitlaufen zu lassen aus denen ich dann die "GruppenIndexes" berechnen und dann den Offset dazunehme. Aber dann habe ich eine weitere Datenstruktur die ich pflegen muss.

Was irgendwie fehlt das man einen weiteren Comparer für die Items innerhalb einer Gruppe anhängen kann.

Vielleicht hat einer eine Idee?

Grüße

Das kenne ich nicht muss ich mal schauen ob das Auswirkungen hat Danke

Hallo Community,

ich versuche mich nach Jahren wieder in WPF reinzuarbeiten, habe aber das Gefühl alles vergessen zu haben. Ich versuche ein CustomControl von einer ComboBox zu bauen das neben der ComboBox einen ResetButton anzeigen zu hat.

 public class ResetableComboBox : ComboBox
    {
        // STATIC PROPERTIES
        public static readonly RoutedEvent ResetEvent;

        // STATIC CONSTRUCTORS
        static ResetableComboBox()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(ResetableComboBox), new FrameworkPropertyMetadata(typeof(ResetableComboBox)));

            ResetEvent = EventManager.RegisterRoutedEvent(nameof(Reset), RoutingStrategy.Bubble, typeof(RoutedEventArgs), typeof(ResetableComboBox));
        }

        // FIELDS
        private Button _resetButton;


        // METHODS
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            _resetButton = Template?.FindName("resetButton", this) as Button;

            if (_resetButton != null)
            {
                _resetButton.Click += ResetButton_Click;
            }
        }

        private void ResetButton_Click(object sender, RoutedEventArgs e) => OnReset();

        protected virtual void OnReset() => RaiseEvent(new RoutedEventArgs(ResetEvent));

        // EVENTHANDLER

        public event RoutedEventHandler Reset
        {
            add { AddHandler(ResetEvent, value); }
            remove { RemoveHandler(ResetEvent, value); }
        }
    }
    }

Der C# Code klappt auch soweit wenn ich den ResetButton drücke dann wird auch das Event geworfen.  In der Generic.xaml habe ich dann in den beiden ComboxTemplates (habe mir per VS > WPF Designer > ComboBox Selektion > Edit Template das komplette Template ausgeben lassen und an mein neues Control angepasst)

<ControlTemplate x:Key="ComboBoxTemplate" TargetType="{x:Type customControls:ResetableComboBox}">
        <Grid x:Name="templateRoot" SnapsToDevicePixels="true">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition MinWidth="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}" Width="0"/>
                <ColumnDefinition MinWidth="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}" Width="0"/>
            </Grid.ColumnDefinitions>
            <Popup x:Name="PART_Popup" AllowsTransparency="true" Grid.ColumnSpan="2" IsOpen="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Margin="1" PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}" Placement="Bottom">
                <Themes:SystemDropShadowChrome x:Name="shadow" Color="Transparent" MaxHeight="{TemplateBinding MaxDropDownHeight}" MinWidth="{Binding ActualWidth, ElementName=templateRoot}">
                    <Border x:Name="dropDownBorder" BorderBrush="{DynamicResource {x:Static SystemColors.WindowFrameBrushKey}}" BorderThickness="1" Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}">
                        <ScrollViewer x:Name="DropDownScrollViewer">
                            <Grid x:Name="grid" RenderOptions.ClearTypeHint="Enabled">
                                <Canvas x:Name="canvas" HorizontalAlignment="Left" Height="0" VerticalAlignment="Top" Width="0">
                                    <Rectangle x:Name="opaqueRect" Fill="{Binding Background, ElementName=dropDownBorder}" Height="{Binding ActualHeight, ElementName=dropDownBorder}" Width="{Binding ActualWidth, ElementName=dropDownBorder}"/>
                                </Canvas>
                                <ItemsPresenter x:Name="ItemsPresenter" KeyboardNavigation.DirectionalNavigation="Contained" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                            </Grid>
                        </ScrollViewer>
                    </Border>
                </Themes:SystemDropShadowChrome>
            </Popup>
            <Button x:Name="resetButton" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Grid.Column="2" Style="{StaticResource ComboBoxResetButton}" Margin="-1,0,0,0" /> 
            <ToggleButton x:Name="toggleButton" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Grid.ColumnSpan="2" IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Style="{StaticResource ComboBoxToggleButton}"/>
            <ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}" ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}" Content="{TemplateBinding SelectionBoxItem}" ContentStringFormat="{TemplateBinding SelectionBoxItemStringFormat}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" IsHitTestVisible="false" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
        </Grid>

Wenn ich nun das ganze in einem Window einbinden klappt auch alles. Meine Frage wäre jetzt, müsste es nicht möglich sein auf Window Ebene ein neuen Style anzulegen für dieses Control.

<Style TargetType="{x:Type customControls:ResetableComboBox}">
            <Setter Property="Background" Value="AliceBlue"/>
        </Style>

Aber das ändert die Farbe nicht. Im WPF Buch von Huber wird im Kapitel "CustomControls" auf Window Ebene  im Style auch das Template überschrieben, ich war aber der Meinung dass das auch so gehen müsste.

Grüße

Daniel

 internal class Rectangle
    {
        public int X { get; set; }
    }

    internal class Control
    {
        private Rectangle _bounds;

        public Control()
        {
            _bounds = new Rectangle { X = 5 };
        }

        public int X => _bounds.X;
    }

    internal class Button : Control
    { 
    
    }

Habe es mal kurz durchgespielt

  static void Main(string[] args)
        {
            var button = new Button();

            Console.WriteLine($"X (OLD): {button.X}");

            // Basisklasse öffentlich, Rectangle Klasse öffentlicht

            var bounds = (Rectangle)typeof(Control)
                                .GetField("_bounds", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)
                                .GetValue(button);
            bounds.X = 6;

            Console.WriteLine($"X (NEW): {button.X}");


            //  Basisklasse nicht öffentlich, Rectangle Klasse nicht öffentlicht

            var boundsOBJ = button
                            .GetType()
                            .BaseType // Rekursiv suchen ggf.
                            .GetField("_bounds", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)
                            .GetValue(button);

            // Autoproperties bekommen einen autogenierten Namen der __BackingField enthält
            boundsOBJ.GetType().GetField("<X>k__BackingField", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).SetValue(boundsOBJ, 20);

            Console.WriteLine($"X (NEW) WAY 2: {button.X}");

            Console.ReadLine();
            
        }

Im wesentlichen  kannst du alles was öffentlich ist auch nutzen für Reflection ansonsten muss man es eben generisch machen. Mit Reflection bekommst du fast alles geliefert und kannst auch Änderungen vornehmen (mit Ausnahmen).  Eventuell falls du Reflection häufig brauchst würde ich über Caching der typen etc. nachdenken. Es gibt einige Blogbeiträge zum Thema Performance bei Reflection.

public ref int X => ref _bounds.X;

Wenn du weißt dass die Property nur ein Fascade für ein zugrundeliegendes Objekt ist, kannst du via Reflection auch die das Object _bounds einfach direct holen und prüfen ob deren X Property ein Setter hat. Ggf. wenn es weitere Objekte gibt hangelst du dich durch. Sollte Xein Auto-Property sein erzeugt der Compiler automatisch ein Feld nach einem bestimmten Namensschema (das kannst du dir i Debugger auslesen). Das Feld solltest du via Reflection schreiben können.

Erstmal ein Dankschön an alle die geantwortet haben. Die Variante mit Exceptionhandling sowie die Sache mit using, habe ich auch jetzt auf dem Schirm. Gerade das Kommentar von Toub finde ich dort sehr hilfreich.

😄 Achso ich versuche gerade die Stelle in den Docs zu finden.

Hallo Community,

ich habe eine Frage zum Thema Task bzw. async/await.


        static async void Main(string[] args)
        {
            await DoSomthingAsync();

            await DoSomthingAsync2();
        }


        static async Task DoSomthingAsync()
        {
            await Calling();
        }

        static Task DoSomthingAsync2()
        {
            return Calling();
        }


        static Task Calling() => Task.Delay(1);

Meine Frage ist ob es einen Unterschied macht, ob ich auf den Task awaite wie in DoSomthingAsync oder den Task durchroute wenn der Aufrufer sowieso ein await macht?

Das einzige was mir auffällt ist dass wenn ich schon ein await mache:


        static async Task DoSomthingAsync3()
        {
            await Calling();
            return Calling();
        }

Das ich dann den letzten Aufruf durchrouten kann.

Cool jetzt funktioniert es wieder und manchmal kann ein Zeichen entscheident sein! Vielen Dank für die Hilfe! 👍

P.S. Gerade noch gefundeb Visual Studio Version Ranges Demystified

Danke für den Hinweis, leider hat sich dadurch nichts geändert. Ob ich die Sprache im Addin ändere oder die VS Spracheinstellung, beides führt zur selben Fehlermeldung!

Hallo Community,

ich stehe im Moment auf dem Schlauch. Ich habe gerade versucht ein selbst geschriebenes VS Addin für das neue VS2019 fit zu machen. Das Addin selber stellt einen Einstellungsdialog bei der Erstellung spezifischer Projekte bereit. Bei der Installation wird angegeben dass dieses Addin für die installierte VS Version nicht installiert werden kann.

12.04.2019 08:31:04 - Microsoft VSIX Installer
12.04.2019 08:31:04 - -------------------------------------------
12.04.2019 08:31:04 - vsixinstaller.exe version:
12.04.2019 08:31:04 - 16.0.2264
12.04.2019 08:31:04 - -------------------------------------------
12.04.2019 08:31:04 - Command line parameters:
12.04.2019 08:31:04 - C:\Program Files (x86)\Microsoft Visual Studio\Installer\resources\app\ServiceHub\Services\Microsoft.VisualStudio.Setup.Service\VSIXInstaller.exe,C:\Repositories\VisualStudioIntegration\Test\bin\Debug\Test.vsix
12.04.2019 08:31:04 - -------------------------------------------
12.04.2019 08:31:04 - Microsoft VSIX Installer
12.04.2019 08:31:04 - -------------------------------------------
12.04.2019 08:31:04 - Initializing Install...
12.04.2019 08:31:05 - Erweiterungsdetails...
12.04.2019 08:31:05 - 	Identifier         : Test.92c071c0-95c3-492f-a523-c8fc6000ad4e
12.04.2019 08:31:05 - 	Name               : Citavi 6 Add-on Template
12.04.2019 08:31:05 - 	Author             : Daniel
12.04.2019 08:31:05 - 	Version            : 0.0.5.0
12.04.2019 08:31:05 - 	Description        : Add a wizard to initialize a new Citavi 6 add-on project.
12.04.2019 08:31:05 - 	Locale             : en-US
12.04.2019 08:31:05 - 	MoreInfoURL        : 
12.04.2019 08:31:05 - 	InstalledByMSI     : False
12.04.2019 08:31:05 - 	SupportedFrameworkVersionRange : [4.6,4.7.2)
12.04.2019 08:31:05 - 
12.04.2019 08:31:05 - 	SignatureState     : Unsigned
12.04.2019 08:31:05 - 	Unterstützte Produkte : 
12.04.2019 08:31:05 - 		Microsoft.VisualStudio.Community
12.04.2019 08:31:05 - 			Version : [15.0,16.0)
12.04.2019 08:31:05 - 		Microsoft.VisualStudio.Pro
12.04.2019 08:31:05 - 			Version : [15.0,16.0)
12.04.2019 08:31:05 - 		Microsoft.VisualStudio.Enterprise
12.04.2019 08:31:05 - 			Version : [15.0,16.0)
12.04.2019 08:31:05 - 
12.04.2019 08:31:05 - 	Verweise           : 
12.04.2019 08:31:05 - 	Voraussetzungen    : 
12.04.2019 08:31:05 - 		-------------------------------------------------------
12.04.2019 08:31:05 - 		Identifier   : Microsoft.VisualStudio.Component.CoreEditor
12.04.2019 08:31:05 - 		Name         : Visual Studio core editor
12.04.2019 08:31:05 - 		Version      : [15.0,16.0)
12.04.2019 08:31:05 - 
12.04.2019 08:31:05 - Signaturdetails...
12.04.2019 08:31:05 - 	Extension is not signed.
12.04.2019 08:31:05 - 
12.04.2019 08:31:05 - Er wird nach passenden Produkten gesucht...
12.04.2019 08:31:05 - Installiertes Produkt gefunden - Globaler Pfad
12.04.2019 08:31:05 - Installiertes Produkt gefunden - Visual Studio Enterprise 2019
12.04.2019 08:31:05 - VSIXInstaller.NoApplicableSKUsException: Diese Erweiterung kann auf den derzeit installierten Produkten nicht installiert werden.
   bei VSIXInstaller.ExtensionService.GetInstallableData(String vsixPath, String extensionPackParentName, Boolean isRepairSupported, IStateData stateData, IEnumerable`1& skuData)
   bei VSIXInstaller.ExtensionPackService.IsExtensionPack(IStateData stateData, Boolean isRepairSupported)
   bei VSIXInstaller.ExtensionPackService.ExpandExtensionPackToInstall(IStateData stateData, Boolean isRepairSupported)
   bei VSIXInstaller.App.Initialize(Boolean isRepairSupported)
   bei VSIXInstaller.App.Initialize()
   bei System.Threading.Tasks.Task`1.InnerInvoke()
   bei System.Threading.Tasks.Task.Execute()
--- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
   bei Microsoft.VisualStudio.Telemetry.WindowsErrorReporting.WatsonReport.GetClrWatsonExceptionInfo(Exception exceptionObject)

Die Versionsnummern (VS19 = 16.0) scheinen laut meinen Recherchen korrekt. Referenziert werden von VS nur die
Microsoft.VisualStudio.TemplateWizardInterface.dll (Version 8.0), envdte.dll (Version 8.0) und die Microsoft.VisualStudio.Coreutility.dll (Version 16.0). Alle Verweise werden gefunden und sind auch korrekt.

Vielleicht hat ja jemand einen Hinweis für mich.

Ich denke dabei geht es vor allem, das die Projekte die noch auf WinForms und WPF bauen einen Grund zu geben, auf .net Core umzusteigen, so dass .net Full das zeitliche segnen kann. Das ist erst mal positiv. Was ich wirklich schade finde ist, dass es kein wirkliches Statement zu einer UI Technologie gibt. Ich arbeite nun seid 8 Jahren mit C# angefangen mit

WinForms
WPF
WinRT
UWP

und nun ist halt Web-Gedöns über PWA der Hype.

Es wäre doch mal ganz angenehm sich für einen Basistechnologie zu entscheiden und dann aber richtig zu promoten und vielleicht auch mal sich zu trauen etwas Cross-Plattform fähiges zu bauen. WPF ist wirklich nice, schade das man jetzt zu dem HTML Gedöns übergegangen ist. Vielleicht gibt es dem ganzen aber noch einen Push für andere Open Source Projekte wie z.B. Avalonia (Da gibt es ja mittlerweile eigene Open Source Editoren)

Wenn man natürlich schaut ist das alles schon eine positive Entwicklung, schauen wir mal wo die Reise hingeht. Wenn jetzt noch VS Open Source werden sollte, dann fr.. ich sprichwörtlich den Besen. 😄

Wobei das nur die .net Core Portierungen sind

This repo contains WinForms for .NET Core. It does not contain the .NET Framework variant of WinForms

Hallo Community,
ich hätte mal eine Frage die wohl eher C++ betrifft als C#. Ich würde gern eine Erweiterung für den Windows Explorer schreiben, so dass dort eine Verknüpfung (vgl Bild im Anhang) und eine Auflistung an Ordnern angezeigt wird wie es bei OneDrive und anderen Dienste (Dropbox macht das glaub ich auch) angezeigt wird. Ich hatte schon mal im Netz geschaut, muss aber gestehen dass ich da nicht weit gekommen bin, weil ich auch nicht genau mir vorstellen kann mit welchen Stichwörter ich suchen sollte. Andere Erweiterungen des Explorers z.B. des Ribbon Bandes oder des Kontextmenu mit C++ oder C# (z.B. Sharpshell) hatte ich schon gefunden.

Vielleicht hat jemand so etwas in der Art schon gemacht oder kann mir einen Tipp geben.

Beste Grüße
Daniel

Das war mir schon klar, die Frage war, wie der Decompiler den Code wieder mit dem Bezeichner herstellt statt mit der ganzen Zahl. Macht er aber gar nicht


public class EnumTestClass
  {
    public EnumTest EnumTestProperty
    {
      get
      {
        return (EnumTest) 1;
      }
    }
  }

Er macht dass nur wenn auch die referenziert DLL woher der Enum stammt gefunden wird. Andernfalls wird korrekterweise die Zahl wiedergegeben. In meinem ersten Test hat er die referenzierte Lib noch gefunden und dann korrekterweise daraus


public class EnumTestClass
  {
    public EnumTest EnumTestProperty => EnumTest.Alpha;
  }

Für meine Ausgangsfrage bedeutet dass aber, dass bei einer Umstellung von einem Enum -> auf ein FlagEnum alle Bibliotheken die dieses Enum verwenden neu kompiliert werden müssen, weil sonst nicht gewährleistet werden kann, dass der richtige EnumWert zugewiesen wird.

Okay dass hat wieder Licht ins Dunkeln gebracht

Also ich habe noch mal geschaut aber irgendwie stehe ich auf dem Schlauch: Soweit ich das mit (ildasm) sehe wird doch nur die ganze Zahlwert gespeichert:

Das Testprojekt ist im Anhang.

Das mit der ersten Frage hatte ich mir schon indirekt gedacht, aber die Frage mit dem Decompiler, wie er das macht. Wenn im IL Code nur eine Ganzzahl steht, dass beim dekombilierten Code wieder der ursprüngliche Bezeichner (z.B. Alpha) wieder steht.

Hallo Community,

ich habe mal zwei Fragen:

1.) Stimmt es dass Enum Werte im IL Code als Zahl gespeichert werden und dann der entsprechende verknüpfte Wert zur Laufzeit geholt wird?

Wenn ja: 2) Wie schaffen es Dekompiler beim wiederherstellen des Codes aus dieser Zahl den korrekten Wert zu ermitteln, also so das wieder der textuelle Wert darsteht?

Hintergrund ist der: Angenommen es gibt zwei Bibliotheken A und B. B referenziert A und hat in seinem Code

Bibliothek A



public enum Test
{
Alpha = 0
Beta = 1,
Gamma =2,
}


Bibliothek B



public Test TestEnum => Test.Gamma;


Wenn mann sich den IL Code anschaut steht da nun die 1. Und daher stellt sich die Frage wie das Decompiler machen, wenn die referenzierte Bibliothek A nicht auf dem Ziel System ist.

Hintergrund ist der, dass es darum geht, aus dem Enum Test -> ein FlagsEnum zu machen, dann ändern sich aber die Zahlen ja, weil es dann 2-Potenzen sein müssen und dass müsste ja dann zu Seiteneffekten kommen, weil dann aus der 2 die in der Bibliothek B kompiliert wird zur Laufzeit vielleicht dann zu Beta wird.

  1. Gibt es da eventuell ein Möglichkeit das zu umgehen?

Beste Grüße

Liebe Community,

wenn man im Windows Explorer eine/mehre Dateien gleichen Datentyps selektieren bekommt man ja im Kontextmenü über "Öffnen mit..." eine Liste der damit verknüpften Programme angezeigt. Genau diese Liste würde ich gern auslesen, so das sich den Pfade und die entsprechenden Parameter um die Liste in einer eigenen Anwendung anzuzeigen und die Programme mit einem Dateipfad zu öffnen. Soweit ich das verstehe muss ich dafür die Registry durchforsten, aber bisher habe ich nur die Standardanwendung und manchmal 1 oder 2 Programme die auch in der Liste standen gefunden, aber nie die komplette Liste. Daher die Frage ob jemand da einen Tipp hat, wie ich diese anzapfen könnte!

Ich habe schon in die Registry geschaut, aber da scheint nicht die original List zu stehen

MfG
Daniel

Ich habe nach längerem Suchen folgende Anleitung gefunden, nach der ich vor gangen bin und dann ging auch alles.

Guten Abend,

ich arbeite gerade mich duch die Anleitung einen Wizard für ein Project Template für Visual Studio zu erstellen. Dazu habe ich die folgende Microsoft-Anleitung mit angeschaut. Woraus ich nicht ganz schlau werde. Am Anfang werden in der Solution drei Projekte erstellt. Eines für das Projekt Template, eins für den Wizard und ds VSIX Projekt. Weiter unten wird aber die IWizard Implementierung aber den VSIX Projekt hinzugefügt. Über sehe ich da etwas?

  1. Frage Mal angenommen ich habe eine 3-Projekt Struktur wie oben beschrieben. Übernimmt der VSIX Installer auch die Registrierung der Wizard-Assembly bei der GAC?

Gruß Daniel

Oder du benutzt eine BulkObservableCollection<T> in dem du die BulkCollection<T> von Visual Studio nimmst oder du baust sie dir selbst.

29.04.2017 - 10:58 Uhr

Hallo Community,
vielen Dank für die Antworten. Ich habe mir alles angeschaut und bin letzten endlich doch beim Google Forms gelandet. Alles etwas einfacher gehalten, aber es hat so weit funktioniert

MfG
Daniel

10.04.2017 - 22:43 Uhr

Es soll so in Richtung poll gehen mit Shared Link. Jemand bekommt einen Link von mir, kann dadurch teilnehmen, hat n-Stimmen (kann ich definieren) die er per Klick auf die verschiedenen Antwortmöglichkeiten verteilen kann. Ich sehe zum Schluss welche die meisten Votes bekommen haben. Man findet einige (ich habe mit Sicherheit noch nicht alle angeschaut), viele bieten soweit ich das sehe nicht die Möglichkeit wie oben beschrieben oder jeder der teilnehmen will, muss sich mit einem Account anmelden (um die Eindeutigkeit der antworten zu gewährleisten)

10.04.2017 - 19:48 Uhr

Hallo Community,

erstmal danke für die Antworten. Zielpublikum sind andere Studenten/Entwickler. Will das für ein paar Studiensachen nutzen. Über die Links bin ich bisher noch nicht wirklich zu einem Ergebnis gekommen. Werde vielleicht mal Google Forms probieren. Wichtig ist, dass die Leute die Antworten sollen keinen Account zu einem Dienst brauchen, quasi via Einladungslink antworten können. Es geht neben Wünschen auch mal darum Vortragsthemen als Ranking darzustellen und wie oben erwähnt auch mal Feature usw. Da für die UNI ist die Sache mit den Issue-Tracker hier etwas zu viel. Sonst hätte ich da mal geschaut.

Gruß
Daniel

08.04.2017 - 19:56 Uhr

Hallo Community,
da ich mit Google nicht so richtig was zufriedenstellendes gefunden habe, frage ich mal hier nach ob jemand einen Tipp hat. Ich suche eine einfache Software (Web) um ein paar Leuten per Link die möglichkeit zu geben aus einer Liste an z.B Wünsche an Softwareentwicklung mt einer von mir festgelegten Anzahl an Votes für Wünsche zu stimmen und ich sehe dann zum Schluss welche Wünsche die meisten Stimmen hat. Muss nichts aufwendiges sein gern kostenls entweder direkt nutzbar ider zum selber hosten.

Gruß
Daniel

Welche Eigenschaften hast du den Beim Button für Anchor und Margin gesetzt?

10.02.2017 - 22:25 Uhr
private void MenuItem_Click(object sender, RoutedEventArgs e)
{

MenuItem MN = sender as MenuItem;
string ImageSender = MN.CommandParameter.ToString();
image_load(ImageSender);

}

Es wurden ja einige Ansätze genannt was du besser machen kannst und willst. Eine spontane Idee (ungetestet) waär im Xaml bei MenuItem die Tag Eigenschaft einfach frech zu nutzen. Dort in RelativSource Binding mit AncestorTyp auf Image Das ja im Visual Tree weiter oben kommen müsste. Dann würdest das oben mit einem cast machen



var menuItem = sender as MenuItem;
var image = menuItem.Tag as Image;
image_load(image);


Musste probieren, ob das so geht. Die anderen Stichwörter das mit MVVM und enem Command machen, waäre auch eher mein Favourit.