Laden...

Forenbeiträge von SteffoD Ingesamt 44 Beiträge

18.10.2018 - 07:26 Uhr

Hi MrSparkle,

ok, danke. Das werde ich mir wohl am WE anschauen. 🙂

16.10.2018 - 15:10 Uhr

Hi MrSparkle,

das ist ein ContentControl, das auf einem Canvas abgelegt wird. Wie gesagt basiert das Programm auf das von pinki verlinkte Tutorial.

Das Problem ist, dass die Elemente dynamisch hinzu kommen und die Objekte (Bilder) eine _beliebige _ Größe haben können, weswegen ich dachte, dass ich auf teilprogrammatische Anweisungen angewiesen bin. Liege ich da falsch?

16.10.2018 - 11:05 Uhr

Hallo an alle,

ich habe mich dem Problem nochmal gewidmet und füge nun das imageItemControl erst hinzu, wenn der Tab geladen wird.

public AssayAreaControl(TabItem imageProcessingMethodTab)
{
	Loaded += OnWindowLoaded;
}

private void OnWindowLoaded(object sender, RoutedEventArgs e)
{
	draw();
}

private void draw()
{
	var imageItemDictionary = new ResourceDictionary
	{
		Source = new Uri("/DiagramDesigner;component/Stencils/ImageItemStyle.xaml",
						 UriKind.RelativeOrAbsolute)
	};

	var imageItemStyle = (Style)imageItemDictionary["ImageItemStyle"];

	ImageItem imageItemControl = new ImageItem
	{
		Style = imageItemStyle,
		Image = image,
		Caption = id,
	};

	// imageItemControl.Width --> NaN
	// imageItemControl.Height --> NaN

	// imageItemControl.ActualWidth --> 0
	// imageItemControl.ActualHeight --> 0
}

Leider stehen mir die Dimensionen des Controls immer noch nicht zur Verfügung. Es liegt vielleicht da dran, dass das Control noch nicht hinzugefügt und gezeichnet wurde.
Bleibt mir nun noch die Möglichkeit, mir die Dimensionen über den Style zusammen zu rechnen. Aber ich gelange wie gesagt nicht an die Höhe des TextBlocks. Wie das mit TemplateParts funktionieren soll, habe ich leider immer noch nicht richtig verstanden...

Weiß jemand weiter?

09.10.2018 - 13:31 Uhr

Hi pinki und Co.,

tatsächlich basiert mein Designer auf dem von dir verlinkten. Das Problem ist, dass ich mehrere Tabs habe und teils Elemente in inaktiven Tabs im Hintergrund geladen werden, die noch nicht im Vordergrund sind, weswegen das Problem auftaucht, dass mir die Größe der Elemente noch nicht zur Verfügung steht.

09.10.2018 - 11:15 Uhr

Hi Palladin007,

um ein besseres Bild zu bekommen: Ich implementiere eine Art Designer. Die Elemente sind frei bewegbar, skalierbar und man kann auch zoomen. Da würde mir Grid nur im Weg stehen, oder?

Dann werde ich wohl versuchen zu rechnen, wenn das Control fertig gezeichnet hat. Danke. 😃

09.10.2018 - 10:40 Uhr

Aber zu deiner eigentlichen Frage:
Das geht nur über TemplateParts. Siehe
>

Dein Problem wird wohl sein, dass Du zuerst versuchst, den TemplatePart vom ContentTemplate zud bekommen und danach vom Control selber, Du brauchst es aber vom Template.

Mir ist leider nicht ganz klar, wie ich das umsetzen soll. Soll ich das Image-Element den Namen PART_ContentHost geben?

09.10.2018 - 10:10 Uhr

Schon die ActualHeight-Property vom Control probiert? Wenn der TextBlock keine Abstände drum herum hat, sollte das ja passen, abgesehen davon ist das die einzige Höhe, die von außen interessieren sollte.

Ich habe dieses Property und auch Height bei imageItemControl abgefragt, aber da der Control zu diesem Zeitpunkt noch nicht sichtbar ist, ist es auf 0 bzw. im letzteren Fall auf _NaN _gesetzt.

Aber wozu brauchst Du die Höhe?

Eigentlich brauche ich die Gesamthöhe vom ImageItem-Control, die mir wie gesagt zu jenem Zeitpunkt noch nicht zur Verfügung steht. Ich brauche das, um die Position des nächsten ImageItem-Element zu berechnen.

09.10.2018 - 09:38 Uhr

Hi Palladin,007,

danke, für deine ausführliche Antwort. 😉
Vielleicht hätte ich mein eigentliches Problem erklären sollen. Ich würde gerne die TextBlock-Höhe in Pixeln ermitteln. Ich hatte mir erhofft, dass ich diese Eigenschaft über die Höhe von TextBlock ermitteln kann. Gibt es noch leichtere Möglichkeiten?

Ich danke im Voraus.

09.10.2018 - 08:41 Uhr

Hallo an alle,

ich habe ein Stil, das ich auf einen Control anwende:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Style x:Key="ImageItemStyle" TargetType="{x:Type ContentControl}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ContentControl}">
                    <StackPanel>
                        <TextBlock Name="tbImageItemCaption" Text="{Binding Caption}" />
                        <Image Source="{Binding Image}" />
                    </StackPanel>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

Der Stil wird auf folgenden Control anwendet:

public class ImageItem : ContentControl
{
	public ImageItem()
	{
		DataContext = this;
	}

	public ImageSource Image { get; set; }
	public string Caption { get; set; }
}

Und so wird er angwendet:

var imageItemDictionary = new ResourceDictionary
{
	Source = new Uri("/DiagramDesigner;component/Stencils/ImageItemStyle.xaml",
					 UriKind.RelativeOrAbsolute)
};

var imageItemStyle = (Style)imageItemDictionary["ImageItemStyle"];

ImageItem imageItemControl = new ImageItem
{
	Style = imageItemStyle,
	Image = image,
	Caption = id,
};

Ich würde nun gerne auf das Element tbImageItemCaption im Stil zugreifen. Allerdings gelingt mir das nicht.

Beide Heransgehensweisen liefern null zurück:

var imageItemCaption1 = imageItemControl.ContentTemplate.FindName("tbImageItemCaption", imageItemControl);
var imageItemCaption2 = imageItemControl.FindName("tbImageItemCaption");

Eine weitere Möglichkeit wäre vielleicht das über Bindings zu lösen, allerdings wüsste icht nicht, wie das genau funktioniert.

Jemand eine Idee?

Danke im Voraus!

01.10.2018 - 07:42 Uhr

Hi MrSparkle,

danke, ich habe mich erst mal eines Workarounds beholfen. Mit MVVM habe ich zwar schon gearbeitet, aber mir wäre erst mal nicht auf Anhieb klar, wie ich das in diesem Fall umsetzen sollte. Dazu bin ich noch nicht Profi genug, zumal ich ständig zwischen C++, Qt, Bildverarbeitung und C#/WPF hin und her springe und mir das ein tiefes Einarbeiten in WPF kaum möglich macht.
Ich werde auf jeden Fall im Hinterkopf behalten öfters ViewModels zu verwenden, wo mir das möglich erscheint. - An einigen Stellen mache ich das wie gesagt schon.

28.09.2018 - 14:44 Uhr

@The69

public static FindCassetteController Instance { get; } = new FindCassetteController();

@Abt
Zu 1: Danke, ich weiß was null ist.
Zu 2: Auch dies ist mir bekannt.
Zu 3: Auch MVC und Co. sind mir bekannt. Es wird ein Bild in die GUI geladen und das Bild muss irgendwie rein kommen. Der Netzwerk-Code ist natürlich nicht direkt in der GUI, stattdessen gelangt das Bild mittels Observer-Pattern in die GUI.

@all: Es scheint, dass ein Property von DesignerControlElement erst bei der Anzeige per lazy evaluation geladen wird. Das muss ich mir mal genauer anschauen...

28.09.2018 - 13:51 Uhr

Hi,
ich habe ein Control den ich in XAML deklariere:

<designerControls:DesignerControl x:Name="DesignerControlElement"/>

In der entsprechenden Klasse wird dieses Control als Parameter übergeben:

public CassetteControl()
{
	InitializeComponent();
	Loaded += OnWindowLoaded;
	DataContext = this;
}

private void OnWindowLoaded(object sender, RoutedEventArgs e)
{
	if (init)
	{
		FindCassetteController.Instance.Subscribe(new BaseImageMessageObserver(DesignerControlElement));
		init = false;
	}
}

Der BaseImageMessageObserver manipuliert dann zu einem späteren Zeitpunkt bei einem Netzwerk-Event den übergebenen DesignerControlElement.

Hier einige Fakten:* CassetteControl befindet sich in einem Tab, der standardmäßig nicht ausgewählt ist

  • OnWindowLoaded() von CassetteControl wird immer ausgeführt, auch wenn der Tab nie ausgewählt wurde.
  • Wenn ich den CassetteControl-Tab vorher auswähle und dann wieder zu einem anderem Tab wechsele und der Netzwerk-Event tritt auf, dann klappt alles.
  • Wenn ich den CassetteControl-Tab vorher nicht ausgewählt habe, wird zwar OnWindowLoaded() ausgeführt, aber sobald der Netzwerk-Event kommt, erhalte ich folgende Fehlermeldung: "Der objektverweis wurde nicht auf eine objektinstanz festgelegt"

Weiß jemand weiter? Ich danke im Voraus! 🙂

L. G.,
Steffo

28.06.2018 - 14:50 Uhr

ImageCaptureControl ist gleichzeitig auch ein Observer. Eigentlich wollte ich nur diese Instanz durchreichen.

28.06.2018 - 13:58 Uhr

Hi MrSparkle,
vielen Dank! Das hat mir viel Arbeit gespart! Seltsam, dass das ohne das Name-Attribut problemlos kompiliert!

Nochmals danke und einen schönen Tag noch!
SteffoD

28.06.2018 - 12:00 Uhr

Hallo,
ich möchte gerne auf ein User Control zugreifen in dem ich ihm einen Namen in XAML gebe.
Versuche ich das, erhalte ich allerdings folgende Fehlermeldung:> Fehlermeldung:

InvalidOperationException: "DisplayMemberPath" und "ItemTemplate" können nicht beide festgelegt werden.

Ich möchte hier auf _ImageCaptureControl _ zugreifen und bekomme besagte Fehlermeldung:

<UserControl x:Class="LR4ConnectionGUI.Controls.ConnectionControl"
             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:LR4ConnectionGUI.Controls"
             xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
             mc:Ignorable="d" >
    <StackPanel>
        <local:ImageCaptureControl x:Name="ImageCapture_Control"/>
    </StackPanel>
</UserControl>

Wenn ich das x:Name Attribut entferne, kompiliert alles.

Das ist das XAML von ImageCaptureControl:

<UserControl x:Class="LR4ConnectionGUI.Controls.ImageCaptureControl"
             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:LR4ConnectionGUI.Controls"
             xmlns:viewmodel="clr-namespace:LR4ConnectionGUI.ViewModel"
             mc:Ignorable="d">
    <GroupBox Margin="10,10,0,10">
        <GroupBox.Header>
            Eingangs-Daten
        </GroupBox.Header>

        <StackPanel>
            <ListView Margin="0, 10, 0, 10"
                      ItemsSource="{Binding Rois}" >
                <ListView.View>
                    <GridView>
                        <GridViewColumn Header="Selektiertes ROI" Width="130" DisplayMemberBinding="{Binding Name}" />
                        <GridViewColumn Header="Oben links" Width="90" DisplayMemberBinding="{Binding TopLeft}" />
                        <GridViewColumn Header="Unten rechts" Width="90" DisplayMemberBinding="{Binding BottomRight}" />
                    </GridView>
                </ListView.View>
            </ListView>

            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="190" />
                    <ColumnDefinition Width="50" />
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto" />
                </Grid.RowDefinitions>

                <Label Content="Mittelung über Anzahl Bilder:"/>
                <TextBox Text="{Binding AveragingOverNumberOfImages}" Grid.Column="1"/>
            </Grid>

            <GroupBox Margin="10,10,0,10">
                <GroupBox.Header>
                    Aufnahme-Modus
                </GroupBox.Header>

                <StackPanel Name="StackPanelImageCapture" HorizontalAlignment="Left">
                    <ComboBox ItemsSource="{Binding ImageCaptureModes}"
                        SelectedValue="{Binding SelectedImageCaptureMode}"
                        DisplayMemberPath="{Binding Name}"
                        SelectionChanged="ImageCaptureMode_SelectionChanged"
                        MinWidth="100">
                        <ComboBox.ItemTemplate>
                            <DataTemplate DataType="{x:Type viewmodel:ImageCaptureModeViewModel}">
                                <TextBlock Text="{Binding Name}"/>
                            </DataTemplate>
                        </ComboBox.ItemTemplate>
                    </ComboBox>
                </StackPanel>
            </GroupBox>
        </StackPanel>
    </GroupBox>
</UserControl>

Weiß jemand weiter?

Danke im Voraus!
SteffoD

26.06.2018 - 14:25 Uhr

Oh, man. Was bist du cool! 😃
Danke, für deine Hilfe und deine Zeit! 😃
Man merkt: Ich bin noch Anfänger! 😉

Liebe Grüße,
SteffoD

26.06.2018 - 11:06 Uhr

Im verlinkten Projekt ist ein Screenshot zu sehen in dem es ein Expander namens "Flow Chart" gibt. Genau diesen Inhalt erwarte ich.

Ich hänge mal das XAML an:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:s="clr-namespace:DiagramDesigner">

    <LinearGradientBrush x:Key="ItemBrush"
                         StartPoint="0,0"
                         EndPoint="0,1">
        <LinearGradientBrush.GradientStops>
            <GradientStop Color="#FEECA1"
                          Offset="0.0" />
            <GradientStop Color="#F18B0F"
                          Offset="1.0" />
        </LinearGradientBrush.GradientStops>
    </LinearGradientBrush>

    <Style x:Key="FlowChartItemStyle"
           TargetType="Path">
        <Setter Property="Fill"
                Value="{StaticResource ItemBrush}" />
        <Setter Property="Stroke"
                Value="#AAA2430F" />
        <Setter Property="StrokeThickness"
                Value="1.5" />
        <Setter Property="StrokeLineJoin"
                Value="Round" />
        <Setter Property="Stretch"
                Value="Fill" />
        <Setter Property="Margin"
                Value="1" />
        <Setter Property="MinWidth"
                Value="10" />
        <Setter Property="MinHeight"
                Value="10" />
        <Setter Property="IsHitTestVisible"
                Value="False" />
        <Setter Property="SnapsToDevicePixels"
                Value="True" />
        <!--<Setter
            Property="Effect">
            <Setter.Value>
                <DropShadowEffect
                    Color="#AADDDDDD"
                    Direction="305"
                    ShadowDepth="7"
                    BlurRadius="3"                    
                    />
            </Setter.Value>
        </Setter>-->
    </Style>

    <!-- Process -->
    <Style x:Key="Process"
           TargetType="Path"
           BasedOn="{StaticResource FlowChartItemStyle}">
        <Setter Property="Data"
                Value="M 0,0 H 60 V40 H 0 Z" />
    </Style>

    <Style x:Key="Process_DragThumb"
           TargetType="Path"
           BasedOn="{StaticResource Process}">
        <Setter Property="IsHitTestVisible"
                Value="true" />
        <Setter Property="Fill"
                Value="Transparent" />
        <Setter Property="Stroke"
                Value="Transparent" />
    </Style>

    <!-- Decision -->
    <Style x:Key="Decision"
           TargetType="Path"
           BasedOn="{StaticResource FlowChartItemStyle}">
        <Setter Property="Data"
                Value="M 0,20 L 30 0 L 60,20 L 30,40 Z" />
    </Style>

    <Style x:Key="Decision_DragThumb"
           TargetType="Path"
           BasedOn="{StaticResource Decision}">
        <Setter Property="IsHitTestVisible"
                Value="true" />
        <Setter Property="Fill"
                Value="Transparent" />
        <Setter Property="Stroke"
                Value="Transparent" />
    </Style>

    <!-- Document -->
    <Style x:Key="Document"
           TargetType="Path"
           BasedOn="{StaticResource FlowChartItemStyle}">
        <Setter Property="Data"
                Value="M 0,0 H 60 V 40 C 30,30 30,50 0,40 Z" />
    </Style>

    <Style x:Key="Document_DragThumb"
           TargetType="Path"
           BasedOn="{StaticResource Document}">
        <Setter Property="IsHitTestVisible"
                Value="true" />
        <Setter Property="Fill"
                Value="Transparent" />
        <Setter Property="Stroke"
                Value="Transparent" />
    </Style>

    <!-- Data -->
    <Style x:Key="Data"
           TargetType="Path"
           BasedOn="{StaticResource FlowChartItemStyle}">
        <Setter Property="Data"
                Value="M 10,0 L 60 0 L 50,40 L 0,40 Z" />
    </Style>

    <Style x:Key="Data_DragThumb"
           TargetType="Path"
           BasedOn="{StaticResource Data}">
        <Setter Property="IsHitTestVisible"
                Value="true" />
        <Setter Property="Fill"
                Value="Transparent" />
        <Setter Property="Stroke"
                Value="Transparent" />
    </Style>

    <!-- Start -->
    <Style x:Key="Start"
           TargetType="Path"
           BasedOn="{StaticResource FlowChartItemStyle}">
        <Setter Property="Data"
                Value="M 10,20 A 20,20 0 1 1 50,20 A 20,20 0 1 1 10,20" />
    </Style>

    <Style x:Key="Start_DragThumb"
           TargetType="Path"
           BasedOn="{StaticResource Start}">
        <Setter Property="IsHitTestVisible"
                Value="true" />
        <Setter Property="Fill"
                Value="Transparent" />
        <Setter Property="Stroke"
                Value="Transparent" />
    </Style>

    <!-- Predefined -->
    <Style x:Key="Predefined"
           TargetType="Path"
           BasedOn="{StaticResource FlowChartItemStyle}">
        <Setter Property="Data"
                Value="M 50,0 V 40 M 10,0 V 40 M 0 0 H 60 V 40 H 0 Z" />
    </Style>

    <Style x:Key="Predefined_DragThumb"
           TargetType="Path"
           BasedOn="{StaticResource Predefined}">
        <Setter Property="IsHitTestVisible"
                Value="true" />
        <Setter Property="Fill"
                Value="Transparent" />
        <Setter Property="Stroke"
                Value="Transparent" />
    </Style>

    <!-- StoredData -->
    <Style x:Key="StoredData"
           TargetType="Path"
           BasedOn="{StaticResource FlowChartItemStyle}">
        <Setter Property="Data"
                Value="M 5,0 H 60 A 40,40 0 0 0 60,40 H 5 A 40,40 0 0 1 5,0 Z" />
    </Style>

    <Style x:Key="StoredData_DragThumb"
           TargetType="Path"
           BasedOn="{StaticResource StoredData}">
        <Setter Property="IsHitTestVisible"
                Value="true" />
        <Setter Property="Fill"
                Value="Transparent" />
        <Setter Property="Stroke"
                Value="Transparent" />
    </Style>

    <!-- InternalStorage -->
    <Style x:Key="InternalStorage"
           TargetType="Path"
           BasedOn="{StaticResource FlowChartItemStyle}">
        <Setter Property="Data"
                Value="M 0,10 H 60 M 10,0 V 40 M 0,0 H 60 V 40 H 0 Z" />
    </Style>

    <Style x:Key="InternalStorage_DragThumb"
           TargetType="Path"
           BasedOn="{StaticResource InternalStorage}">
        <Setter Property="IsHitTestVisible"
                Value="true" />
        <Setter Property="Fill"
                Value="Transparent" />
        <Setter Property="Stroke"
                Value="Transparent" />
    </Style>

    <!-- SequentialData -->
    <Style x:Key="SequentialData"
           TargetType="Path"
           BasedOn="{StaticResource FlowChartItemStyle}">
        <Setter Property="Data"
                Value="M 30,40 A 20,20 0 1 1 30,0 A 20,20 0 0 1 43,35 H 50 L 50,40 Z" />
    </Style>

    <Style x:Key="SequentialData_DragThumb"
           TargetType="Path"
           BasedOn="{StaticResource SequentialData}">
        <Setter Property="IsHitTestVisible"
                Value="true" />
        <Setter Property="Fill"
                Value="Transparent" />
        <Setter Property="Stroke"
                Value="Transparent" />
    </Style>

    <!-- DirectData -->
    <Style x:Key="DirectData"
           TargetType="Path"
           BasedOn="{StaticResource FlowChartItemStyle}">
        <Setter Property="Data"
                Value="F 1 M 57,40 H 3 A 4,20 0 1 1 3,0 H 57 A 4,20.1 0 1 1 56,0" />
    </Style>

    <Style x:Key="DirectData_DragThumb"
           TargetType="Path"
           BasedOn="{StaticResource DirectData}">
        <Setter Property="IsHitTestVisible"
                Value="true" />
        <Setter Property="Fill"
                Value="Transparent" />
        <Setter Property="Stroke"
                Value="Transparent" />
    </Style>

    <!-- ManualInput -->
    <Style x:Key="ManualInput"
           TargetType="Path"
           BasedOn="{StaticResource FlowChartItemStyle}">
        <Setter Property="Data"
                Value="M 0 10 L 60,0 V 40 H 0 Z" />
    </Style>

    <Style x:Key="ManualInput_DragThumb"
           TargetType="Path"
           BasedOn="{StaticResource ManualInput}">
        <Setter Property="IsHitTestVisible"
                Value="true" />
        <Setter Property="Fill"
                Value="Transparent" />
        <Setter Property="Stroke"
                Value="Transparent" />
    </Style>

    <!-- Card -->
    <Style x:Key="Card"
           TargetType="Path"
           BasedOn="{StaticResource FlowChartItemStyle}">
        <Setter Property="Data"
                Value="M 0 10 L 10,0 H 60 V 40 H 0 Z" />
    </Style>

    <Style x:Key="Card_DragThumb"
           TargetType="Path"
           BasedOn="{StaticResource Card}">
        <Setter Property="IsHitTestVisible"
                Value="true" />
        <Setter Property="Fill"
                Value="Transparent" />
        <Setter Property="Stroke"
                Value="Transparent" />
    </Style>

    <!-- PaperTape -->
    <Style x:Key="PaperTape"
           TargetType="Path"
           BasedOn="{StaticResource FlowChartItemStyle}">
        <Setter Property="Data"
                Value="M 0,3 C 30,-7 30,13 60,3 V 37 C 30,47 30,27 0,37 Z" />
    </Style>

    <Style x:Key="PaperTape_DragThumb"
           TargetType="Path"
           BasedOn="{StaticResource PaperTape}">
        <Setter Property="IsHitTestVisible"
                Value="true" />
        <Setter Property="Fill"
                Value="Transparent" />
        <Setter Property="Stroke"
                Value="Transparent" />
    </Style>

    <!-- Delay -->
    <Style x:Key="Delay"
           TargetType="Path"
           BasedOn="{StaticResource FlowChartItemStyle}">
        <Setter Property="Data"
                Value="M 0,0 H 40 A 20,20 0 0 1 40,40 H 0 Z" />
    </Style>

    <Style x:Key="Delay_DragThumb"
           TargetType="Path"
           BasedOn="{StaticResource Delay}">
        <Setter Property="IsHitTestVisible"
                Value="true" />
        <Setter Property="Fill"
                Value="Transparent" />
        <Setter Property="Stroke"
                Value="Transparent" />
    </Style>

    <!-- Terminator -->
    <Style x:Key="Terminator"
           TargetType="Path"
           BasedOn="{StaticResource FlowChartItemStyle}">
        <Setter Property="Data"
                Value="M 20,40 A 20,20 0 0 1 20,0 H 40 A 20,20 0 0 1 40,40 Z" />
    </Style>

    <Style x:Key="Terminator_DragThumb"
           TargetType="Path"
           BasedOn="{StaticResource Terminator}">
        <Setter Property="IsHitTestVisible"
                Value="true" />
        <Setter Property="Fill"
                Value="Transparent" />
        <Setter Property="Stroke"
                Value="Transparent" />
    </Style>

    <!-- Display -->
    <Style x:Key="Display"
           TargetType="Path"
           BasedOn="{StaticResource FlowChartItemStyle}">
        <Setter Property="Data"
                Value="M 0,20 A 40,40 0 0 1 15,0 H 55 A 60,60 0 0 1 55,40 H 15 A 40,40, 0 0 1 0,20 Z" />
    </Style>

    <Style x:Key="Display_DragThumb"
           TargetType="Path"
           BasedOn="{StaticResource Display}">
        <Setter Property="IsHitTestVisible"
                Value="true" />
        <Setter Property="Fill"
                Value="Transparent" />
        <Setter Property="Stroke"
                Value="Transparent" />
    </Style>

    <!-- LoopLimit -->
    <Style x:Key="LoopLimit"
           TargetType="Path"
           BasedOn="{StaticResource FlowChartItemStyle}">
        <Setter Property="Data"
                Value="M 0 10 L 10,0 H 50 L 60,10 V 40 H 0 Z" />
    </Style>

    <Style x:Key="LoopLimit_DragThumb"
           TargetType="Path"
           BasedOn="{StaticResource LoopLimit}">
        <Setter Property="IsHitTestVisible"
                Value="true" />
        <Setter Property="Fill"
                Value="Transparent" />
        <Setter Property="Stroke"
                Value="Transparent" />
    </Style>

    <!-- Preparation -->
    <Style x:Key="Preparation"
           TargetType="Path"
           BasedOn="{StaticResource FlowChartItemStyle}">
        <Setter Property="Data"
                Value="M 0,20 L 10,0  H 50 L 60,20 L 50,40 H10 Z" />
    </Style>

    <Style x:Key="Preparation_DragThumb"
           TargetType="Path"
           BasedOn="{StaticResource Preparation}">
        <Setter Property="IsHitTestVisible"
                Value="true" />
        <Setter Property="Fill"
                Value="Transparent" />
        <Setter Property="Stroke"
                Value="Transparent" />
    </Style>

    <!-- ManualOperation -->
    <Style x:Key="ManualOperation"
           TargetType="Path"
           BasedOn="{StaticResource FlowChartItemStyle}">
        <Setter Property="Data"
                Value="M 0 0 H 60 L 50 40 H 10 Z" />
    </Style>

    <Style x:Key="ManualOperation_DragThumb"
           TargetType="Path"
           BasedOn="{StaticResource ManualOperation}">
        <Setter Property="IsHitTestVisible"
                Value="true" />
        <Setter Property="Fill"
                Value="Transparent" />
        <Setter Property="Stroke"
                Value="Transparent" />
    </Style>

    <!-- OffPageReference -->
    <Style x:Key="OffPageReference"
           TargetType="Path"
           BasedOn="{StaticResource FlowChartItemStyle}">
        <Setter Property="Data"
                Value="M 0 0 H 60 V 20 L 30,40 L 0,20 Z" />
    </Style>

    <Style x:Key="OffPageReference_DragThumb"
           TargetType="Path"
           BasedOn="{StaticResource OffPageReference}">
        <Setter Property="IsHitTestVisible"
                Value="true" />
        <Setter Property="Fill"
                Value="Transparent" />
        <Setter Property="Stroke"
                Value="Transparent" />
    </Style>

    <!-- Star -->
    <Style x:Key="Star"
           TargetType="Path"
           BasedOn="{StaticResource FlowChartItemStyle}">
        <Setter Property="Data"
                Value="M 9,2 11,7 17,7 12,10 14,15 9,12 4,15 6,10 1,7 7,7 Z" />
    </Style>

    <Style x:Key="Star_DragThumb"
           TargetType="Path"
           BasedOn="{StaticResource Star}">
        <Setter Property="IsHitTestVisible"
                Value="true" />
        <Setter Property="Fill"
                Value="Transparent" />
        <Setter Property="Stroke"
                Value="Transparent" />
    </Style>

    <!-- Toolbox -->
    <s:Toolbox x:Key="FlowChartSymbols"
               DefaultItemSize="55,40"
               SnapsToDevicePixels="True"
               ScrollViewer.HorizontalScrollBarVisibility="Disabled">
        <ItemsControl.Items>

            <Path Style="{StaticResource Process}"
                  MinWidth="35"
                  MinHeight="20"
                  ToolTip="Process">

                <s:DesignerItem.MoveThumbTemplate>
                    <ControlTemplate>
                        <Path Style="{StaticResource Process_DragThumb}" />
                    </ControlTemplate>
                </s:DesignerItem.MoveThumbTemplate>
            </Path>

            <ContentControl MinWidth="5" MinHeight="5">
                <Rectangle Stroke="Red" StrokeThickness="7"/>
            </ContentControl>

            <Path Style="{StaticResource Decision}"
                  ToolTip="Decision">
                <s:DesignerItem.MoveThumbTemplate>
                    <ControlTemplate>
                        <Path Style="{StaticResource Decision_DragThumb}" />
                    </ControlTemplate>
                </s:DesignerItem.MoveThumbTemplate>
            </Path>

            <Path Style="{StaticResource Document}"
                  ToolTip="Document">
                <s:DesignerItem.MoveThumbTemplate>
                    <ControlTemplate>
                        <Path Style="{StaticResource Document_DragThumb}" />
                    </ControlTemplate>
                </s:DesignerItem.MoveThumbTemplate>

            </Path>

            <Path Style="{StaticResource Data}"
                  ToolTip="Data">
                <s:DesignerItem.MoveThumbTemplate>
                    <ControlTemplate>
                        <Path Style="{StaticResource Data_DragThumb}" />
                    </ControlTemplate>
                </s:DesignerItem.MoveThumbTemplate>

            </Path>

            <Path Style="{StaticResource Start}"
                  ToolTip="Start">
                <s:DesignerItem.MoveThumbTemplate>
                    <ControlTemplate>
                        <Path Style="{StaticResource Start_DragThumb}" />
                    </ControlTemplate>
                </s:DesignerItem.MoveThumbTemplate>
            </Path>

            <Path Style="{StaticResource PaperTape}"
                  ToolTip="Paper Tape">
                <s:DesignerItem.MoveThumbTemplate>
                    <ControlTemplate>
                        <Path Style="{StaticResource PaperTape_DragThumb}" />
                    </ControlTemplate>
                </s:DesignerItem.MoveThumbTemplate>

            </Path>

            <Path Style="{StaticResource Predefined}"
                  ToolTip="Predefined">
                <s:DesignerItem.MoveThumbTemplate>
                    <ControlTemplate>
                        <Path Style="{StaticResource Predefined_DragThumb}" />
                    </ControlTemplate>
                </s:DesignerItem.MoveThumbTemplate>
            </Path>

            <Path Style="{StaticResource StoredData}"
                  ToolTip="Stored Data">
                <s:DesignerItem.MoveThumbTemplate>
                    <ControlTemplate>
                        <Path Style="{StaticResource StoredData_DragThumb}" />
                    </ControlTemplate>
                </s:DesignerItem.MoveThumbTemplate>

            </Path>

            <Path Style="{StaticResource InternalStorage}"
                  ToolTip="Internal Storage">
                <s:DesignerItem.MoveThumbTemplate>
                    <ControlTemplate>
                        <Path Style="{StaticResource InternalStorage_DragThumb}" />
                    </ControlTemplate>
                </s:DesignerItem.MoveThumbTemplate>
            </Path>

            <Path Style="{StaticResource SequentialData}"
                  ToolTip="Sequential Data">
                <s:DesignerItem.MoveThumbTemplate>
                    <ControlTemplate>
                        <Path Style="{StaticResource SequentialData_DragThumb}" />
                    </ControlTemplate>
                </s:DesignerItem.MoveThumbTemplate>
            </Path>

            <Path Style="{StaticResource DirectData}"
                  ToolTip="Direct Data">
                <s:DesignerItem.MoveThumbTemplate>
                    <ControlTemplate>
                        <Path Style="{StaticResource DirectData_DragThumb}" />
                    </ControlTemplate>
                </s:DesignerItem.MoveThumbTemplate>
            </Path>

            <Path Style="{StaticResource ManualInput}"
                  ToolTip="Manual Input">
                <s:DesignerItem.MoveThumbTemplate>
                    <ControlTemplate>
                        <Path Style="{StaticResource ManualInput_DragThumb}" />
                    </ControlTemplate>
                </s:DesignerItem.MoveThumbTemplate>
            </Path>

        </ItemsControl.Items>
    </s:Toolbox>
</ResourceDictionary>

26.06.2018 - 09:57 Uhr

Hallo p!lle,
danke, für deine Antwort. Ich gebe der Ressource zumindest keinen expliziten Namen über x:Key. In der Ausgabe sehe ich ebenfalls keine Fehlermeldungen.
DesignerControl ist ebenfalls von mir.
Auf das Assembly greife ich zu, in dem ich das DiagramDesigner-Projekt über Visual Studio einbinde und dann vom anderen Projekt darauf verweise.
Kurz gesagt: Ich habe aus diesem Projekt eine Lib gemacht auf der ich dann von meinem Projekt aus zugreife. Davor war das eine Applikation und ich greife genau gleich auf das Control und auf die Ressource zu wie zuvor in der Applikation.

25.06.2018 - 15:35 Uhr

Hallo,
danke für eure Antworten. Der Namensraum und der Assembly-Name ist DiagramDesigner und die Datei existiert auch (sonst würde erst gar nicht kompiliert werden). Es wird allerdings einfach nichts im Expander angezeigt. Gleiches gilt für das Control DesignerControl :

<Window x:Class="LR4ProductionGui.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:designerControls="clr-namespace:DiagramDesigner.Controls;assembly=DiagramDesigner"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">

<!-- ... -->

<Border Margin="3,1,0,0"
                    Grid.Column="1"
                    BorderBrush="LightGray"
                    BorderThickness="1">
                    <designerControls:DesignerControl x:Name="DesignerControl"/>
                </Border>

Hier wird einfach nur eine weiße Fläche angezeigt. Ein Zoom-Slider fehlt hier.

25.06.2018 - 13:49 Uhr

Grüß Gott allerseits,

ich würde gerne auf eine xaml-Ressource in einer anderen Assembly verweisen. Ich habe hierzu die Ressource _FlowChartSymbols _ in MergedDictionaries angegeben:

<Window.Resources>
	<ResourceDictionary>
		<ResourceDictionary.MergedDictionaries>
			<ResourceDictionary Source="pack://application:,,,/DiagramDesigner;component/Stencils/FlowChartSymbols.xaml" />
		</ResourceDictionary.MergedDictionaries>
	</ResourceDictionary>
</Window.Resources>

<!-- ... -->

<Expander IsExpanded="False"
          Header="Flow Chart"
          Margin="0,1,0,0"
          Content="{StaticResource FlowChartSymbols}" />


Allerdings werden, wenn die Applikation ausgeführt wird, keinerlei Elemente angezeigt.
Weiß jemand weiter?

Danke im Voraus.

Gruß,
SteffoD

13.04.2018 - 14:19 Uhr

Danke, InnoSetup klingt interessant.
Momentan habe ich das vorerst mal so gelöst, dass die Lib auf Datei-System-Ebene verlinkt wird.

12.04.2018 - 08:52 Uhr

Hallo an alle,

da ClickOnce bei mir die Abhängigkeiten nicht richtig aufgelöst hat (es haben zu viele gefehlt), bin ich zu Visual Studio Installer Extension gewechselt. Das hat die Abhängigkeiten alle richtig aufgelöst, bis ich irgendwann eine .Net Standard Lib eingebunden habe. Nun werden bei den Abhängigkeiten viele doppelte dlls aufgelistet, die zum Teil zu Laufzeitfehlern bei meiner installierten Applikation führen.
Ich konnte vorerst eine dll identifizieren die Probleme macht und diese ausschließen. Bei weiteren Experimenten bzw. dlls habe ich gemerkt, dass ich nicht immer die richtige dll ausgeschlossen habe und es kam wieder zu Laufzeitfehlern.
Meine Frage ist, wie man das sauber lösen kann.

Danke im Voraus für alle Tipps!

Viele Grüße,
SteffoD

03.04.2018 - 16:49 Uhr

@MrSparcle: Danke, aber wie gesagt: Ich will keine benutzerspezifischen Daten schreiben, sondern Applikationsdaten. In .Net sind App-Settings leider read only.

@Tapi88: Danke, das sieht gut aus! Werde ich mir mal anschauen! 😃

03.04.2018 - 15:32 Uhr

Hallo,

ich habe eine WPF-Applikation in der Settings sowohl gelesen als auch beschrieben werden sollen. Mit .Net Boardmitteln habe ich das nicht hinbekommen. Daher speichere ich eine einfache Json-Datei im Applikations-Ordner ab, da die Settings für alle Nutzer des PCs gelten sollen.

Mein Problem ist, dass ich die Settings im Applikations-Ordner, der sich unter C:\Programme befindet, nicht ohne Adminrechte modifizieren kann.

Wie kann ich das Problem umgehen? Aus Komfortgründen sollten die Einstellungen global sein, sonst müsste z. B. die Server-Adresse pro Benutzer neu eingestellt werden, was der Endbenutzer nicht akzeptieren würde.

Danke im Voraus für hilfreiche Tipps!
SteffoD

28.03.2018 - 23:29 Uhr

Optional können Tasks explizit zur Ausführung auf einem separaten Thread über die Task.Run-API angefordert werden.

Dennoch danke für deine Hilfe. 😃

28.03.2018 - 23:16 Uhr

Du beschreibst hier mit dem Wunsch an Task Parallelität ("Task loszuschicken und währenddessen etwas anderes zu machen"): async/await hat aber mit Parallelität nichts zutun.

Ohne dich jetzt auf die Palme bringen zu wollen: Aber async/await kann asynchron innerhalb eines Threads bedeuten oder auch dass ein neuer Thread kreiert wird und damit ist es dann parallel.
Ich gebe zu, dass ich da am Anfang ungenau war, aber zu sagen, dass async/await nichts mit Parallelität zu tun hat, ist auch nicht richtig.

28.03.2018 - 23:04 Uhr

Gut asynchron bedeutet, dass man die Kontrolle wieder dem Aufrufer zurückgibt solange die Task am Arbeiten ist. Das ist bei der GUI z. B. wichtig.
Aber wie ist das bei Kestrel? Wird da nicht sowieso pro Request eine Task erstellt?

28.03.2018 - 22:42 Uhr

Da bei mir der Client beim Start 3-4 Requests gleichzeitig startet und nach der Rolle fragt, kam es bei mir ohne Locking schon zu Exceptions, da ein gerade hinzugefügter User nochmals hinzugefügt wurde.
WAS für eine Exception? Ich kann leider immer noch nicht hellsehen 😉
Eine Exception, dass der Benutzer bereits existiert?
BINGO. Genau das willst Du.

Wenn Du diese Exception bekommst, dann lade doch an der Stelle den Benutzer nochmal erneut und gebe den dann zurück: fertig.

Das werde ich mal versuchen, danke.

Und PS: bitte verwende asynchrone Methoden wo immer Du nur kannst.
In ASP.NET Core werden bald nur noch asynchrone Actions möglich sein (so wie es bei mobilen Anwendungen auch heute schon ist).

Ich hatte vorher alles mit Async-Methoden. Der Witz war aber, dass davor immer ein await war. Also z. B. halte ich await SingleOrDefaultAsync() für witzlos, da die Methode durch await foo() synchron ausgeführt wird. Durch den Overhead kann die Applikation dann langsamer laufen. Siehe diesen Issue. In dem Issue wird auch gezeigt, wie man es richtig macht, nur ergibt sich diese Möglichkeit bei mir nicht, da ich in der nächsten Zeile schon wieder das Ergebnis verarbeiten muss. Es nützt also wenig, wenn ich eine Task losschicke und in der nächsten Zeile auf die Task warte. Was dagegen hilft ist eine Task loszuschicken und währenddessen etwas anderes zu machen und irgendwann ein await aufrufen. Oder sehe ich das falsch?

28.03.2018 - 22:14 Uhr

Und wie gesagt: für die Eindeutigkeit hier ist das Datenbank-Schema verantwortlich.
Wieso nutzt Du es nicht? Allein diese Mini-Änderung macht Dein Locking unnötig.

Was meinst du mit Eindeutigkeit? Die Usernamen sind bei mir eindeutig und wenn ich versuche denselben User nochmals hinzuzufügen, wird eine Exception geworfen.
Da bei mir der Client beim Start 3-4 Requests gleichzeitig startet und nach der Rolle fragt, kam es bei mir ohne Locking schon zu Exceptions, da ein gerade hinzugefügter User nochmals hinzugefügt wurde.

Weil Du mir nicht glaubst, oder Du es technisch nicht nachvollziehen kannst?
Was hab ich davon Dir Quatsch zu erzählen? 😃

Ich meinte, dass Locking ausschließlich bei Multithreading-Anwendungen Sinn macht. Du hast angedeutet, dass man gerade dort kein Locking verwenden sollte.

28.03.2018 - 22:10 Uhr

Ich könnte die Task fein sauber in drei Tasks unterteilen:

  • bool UserExists(string user): Existiert ein User in der DB?
  • void AddUser(string user): Falls nein, füge den User hinzu
  • Role GetRole(string user): Gibt lediglich die Rolle eines Users zurück

Das sind drei Requests die zusammengenommen mehr Performance kosten würden.
Weiter kommt noch hinzu, dass GetRole() eine Funktion ist, die nur bei Programmstart des Client ca. 3-4 mal von 3-4 Tasks gleichzeitig aufgerufen wird. Danach wird das Ergebnis von der jeweiligen Klasse gecacht. Ist also ein seltener Aufruf, wo ich mir über Performance keine großen Gedanken machen muss.
Was ich eher machen würde: Den Request in meinem Client nur einmal zu machen und das Ergebnis global zu cachen.

Wie würdest du das machen?

28.03.2018 - 21:56 Uhr

Danke, für deine Antwort.
Ich bin dennoch der Ansicht, dass man um das eigentliche Problem drum herum redet. D. h.: Weshalb stürzt die Anwendung komplett ab, wenn Locking genutzt? Kann das auch in anderen Konstellationen auftauchen?

Meine Funktion fügt nicht nur einen Admin hinzu, sondern auch normale User mit der Rolle "User" sofern sie in der DB nicht existieren. Dieses Verhalten halte ich für sinnvoll, da das eine Intranet-Anwendung ist, in der User automatisch hinzugefügt werden sollen, sofern sie in der DB nicht existieren und nur der erste User wird Admin.

Locking ist außerdem GERADE in Multithreading-Anwendung ein absolut legitimes Mittel, da man das bei synchronen Anwendungen sowieso nicht braucht. 😉
Von daher kann ich deine Einwände nicht richtig nachvollziehen außer dass man natürlich versuchen sollte das Locking zu minimieren, sofern möglich.

28.03.2018 - 13:54 Uhr

Nicht gefangene Exceptions werden geloggt. Siehe den anderen Thread.

Soweit ich weiß, wird für jeden Request eine neue Controller-Instanz erstellt. Daher mein Gedanke, dass der Lock statisch ist. Auch wenn der statische Lock nicht sauber ist, dürfte er eigentlich nicht falsch sein.
Der DBContext ist ebenfalls _kein _Singleton, wie hier zu sehen ist:

public void ConfigureServices(IServiceCollection services)
{
	services.AddDbContext<QlcContext>();
	
	services.AddMvc();
}

Ein try/catch um den Funktions-Rumpf hat auch nicht geholfen:

[HttpGet]
[Route("GetRole")]
public IActionResult GetRole(string user)
{
	if (String.IsNullOrEmpty(user))
	{
		_logger.LogError("Missing user parameter");
		return BadRequest("Missing user parameter");
	}

	try
	{
		QlcUser foundUser;

		lock (userRoleCheckLock)
		{
			foundUser = _dbContext.QlcUser.SingleOrDefault(u => string.Equals(u.Name, user, StringComparison.InvariantCultureIgnoreCase));

			if (foundUser == null)
			{
				// If the user table is empty, then the first user which logs in, is admin else it is an normal user
				bool isAdmin = _dbContext.QlcUser.Count() == 0;
				Role role = isAdmin ? Role.Admin : Role.User;
				foundUser = new QlcUser { Name = user, Role = role };

				Log(Severity.TRACE,
					$"Database user table is empty. Creating first user '{user}' with the role '{foundUser.RoleDisplayName}'",
					user);

				_dbContext.QlcUser.Add(foundUser);
				_dbContext.SaveChanges();
			}
		}

		return Ok(foundUser.Role);
	}
	catch (Exception ex)
	{
		_logger.LogError(ex.ToString());
	}
	return BadRequest();
}

Aber Einträge zum Start sollten schon in der Ereignisanzeige stehen oder?

Ich sehe da nichts. Ist das normal?

Haben denn verschiedene Clients die gleiche Controller-Instanz? Ansonsten ist doch hier eine Thread-Synchronisierung überhaupt nicht zielführend da die Clients sowieso unter verschiedenen Kontexten laufen.

Haben sie nicht, deswegen der statische Lock. Es soll kein gleichzeitiger DB-Look-Up gemacht werden.

28.03.2018 - 12:55 Uhr

Hi T-Virus,
danke, für deine Antwort. Ja, ich habe den Code nochmal gedebuggt und er macht was er soll.
Bei der Windows-Ereignis-Anzeige konnte ich nichts finden. Sowohl unter der Rubrik "Fehler" als auch unter "Kritisch", "Warnung" und "Anwendung" nichts.

Ziemlich frustrierend das Ganze. Das beschäftigt mich schon seit Wochen...

Viele Grüße,
Steffo

28.03.2018 - 11:43 Uhr

Hi an alle,

ich habe eine HTTP Schnittstelle die nach User-Rollen sucht.

Es gibt hierbei einen Spezialfall: Wenn die DB leer ist, dann wird automatisch ein Benutzer mit der Rolle "Admin" erstellt. Diese Prüfung ist vom Design her nicht thread-safe. Deshalb habe ich ein statisches Objekt erstellt das als Lock dient, siehe den unteren Code:

public class UserManagement : Controller
{
	private readonly QlcContext _dbContext;
	private readonly ILogger<UserManagement> _logger;
	private static Object userRoleCheckLock = new Object(); 

	public UserManagement(QlcContext dbContext, ILogger<UserManagement> logger)
	{
		_dbContext = dbContext;
		_logger = logger;
	}

	[HttpGet]
	[Route("GetRole")]
	public IActionResult GetRole(string user)
	{
		if (String.IsNullOrEmpty(user))
		{
			_logger.LogError("Missing user parameter");
			return BadRequest("Missing user parameter");
		}

		QlcUser foundUser;

		lock (userRoleCheckLock)
		{
			foundUser = _dbContext.QlcUser.SingleOrDefault(u => string.Equals(u.Name, user, StringComparison.InvariantCultureIgnoreCase));

			if (foundUser == null)
			{
				// If the user table is empty, then the first user which logs in, is admin else it is an normal user
				bool isAdmin = _dbContext.QlcUser.Count() == 0;
				Role role = isAdmin ? Role.Admin : Role.User;
				foundUser = new QlcUser { Name = user, Role = role };

				Log(Severity.TRACE,
					$"Database user table is empty. Creating first user '{user}' with the role '{foundUser.RoleDisplayName}'",
					user);

				_dbContext.QlcUser.Add(foundUser);
				_dbContext.SaveChanges();
			}
		}

		return Ok(foundUser.Role);
	}
	
	private void Log(Severity severity, string message, string requestor)
	{
		AuditTrail auditTrail = new AuditTrail(
			severity,
			DateTime.UtcNow,
			requestor,
			message);

		_dbContext.AuditTrail.Add(auditTrail);
		_dbContext.SaveChanges();
	}
}

Das Problem ist, dass ich regelmäßg Abstürze bekomme. Die komplette ASP.Net Anwendung stürzt ohne jegliche Exceptions und ohne jegliche Logs ab! Wie ist das möglich? Sollte das nicht funktionieren?!

Danke im Voraus für hilfreiche Tipps!

Viele Grüße,
SteffoD

23.03.2018 - 15:33 Uhr

Danke, aber der Crash wird leider immer noch nicht geloggt.
Ist es überhaupt möglich Unmanaged Code von C# zu loggen?

Angenommen es gibt ein Segmentation Fault, kann das C# im Release Mode loggen?

23.03.2018 - 13:37 Uhr

Hi an alle,

ich habe eine ASP.Net Core Applikation die nur im Release-Modus komplett abstürzt. Obwohl ich NLog installiert und konfiguert habe, wird in diesem speziellen Fall nichts geloggt.

Ich habe einen globalen Exception-Handler in Startup regristriert:

public class Startup
{
	private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
	
	// ...
	
	public void Configure(IApplicationBuilder app, IHostingEnvironment env)
	{
		if (env.IsDevelopment())
		{
			app.UseDeveloperExceptionPage();
		}

		app.UseMvc();

		app.UseExceptionHandler(
		 options => {
			 options.Run(
			 async context =>
			 {
				 context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
				 context.Response.ContentType = "text/html";
				 var ex = context.Features.Get<IExceptionHandlerFeature>();
				 if (ex != null)
				 {
					 var err = $"<h1>Error: {ex.Error.Message}</h1>{ex.Error.StackTrace }";
					 await context.Response.WriteAsync(err).ConfigureAwait(false);
					 logger.Fatal(ex);
				 }
			 });
		 }
		);
	}
}

In Program regristriere ich NLog als Logger:

public class Program
{
	public static void Main(string[] args)
	{
		// NLog: setup the logger first to catch all errors
		var logger = LogManager.LoadConfiguration("nlog.config").GetCurrentClassLogger();
		try
		{
			logger.Debug("init main");
			BuildWebHost(args).Run();
		}
		catch (Exception ex)
		{
			//NLog: catch setup errors
			logger.Error(ex, "Stopped program because of exception");
			throw;
		}
		finally
		{
			// Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux)
			NLog.LogManager.Shutdown();
		}
	}

	public static IWebHost BuildWebHost(string[] args)
	{
		return WebHost.CreateDefaultBuilder(args)
			.UseStartup<Startup>()
			.UseKestrel(options =>
			{
				options.Listen(IPAddress.Any, 55555)
			.UseNLog()  // NLog: setup NLog for Dependency injection
			.Build();
	}
}

Meine nlog.config:

<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      autoReload="true"
      internalLogLevel="info"
      internalLogFile="c:\temp\internal-nlog.txt">


  <!-- the targets to write to -->
  <targets>
    <!-- write logs to file  -->
    <target xsi:type="File" name="allfile" fileName="QlcLog-All-${shortdate}.log"
            layout="${longdate}|${event-properties:item=EventId_Id}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}" />

    <!-- another file log, only own logs. Uses some ASP.NET core renderers -->
    <target xsi:type="File" name="ownFile-web" fileName="QlcLog-Own-${shortdate}.log"
            layout="${longdate}|${event-properties:item=EventId_Id}|${assembly-version}|${uppercase:${level}}|${logger}|${callsite}|${callsite-linenumber}|${message} ${exception:format=tostring}|url: ${aspnet-request-url}|action: ${aspnet-mvc-action}" />
  </targets>

  <!-- rules to map from logger name to target -->
  <rules>
    <!--All logs, including from Microsoft-->
    <logger name="*" minlevel="Error" writeTo="allfile" />

    <!--Skip non-critical Microsoft logs and so log only own logs-->
    <logger name="Microsoft.*" maxLevel="Error" final="true" />
    <!-- Own logs -->
    <logger name="*" minlevel="Warn" writeTo="ownFile-web" />
  </rules>

  <extensions>
    <add assembly="NLog.Web.AspNetCore"/>
  </extensions>
</nlog>

Wenn eine Exception auftaucht, wird sie normalerweise in der Konsole und in der Log-Datei geloggt. Nur in einem Fall, in der die Applikation komplett im Release-Mode abstürzt, wird absolut nichts geloggt.

Ich spekuliere dass das von Unmanaged Code verursacht wird, den ich indirekt nutze (SQLite-Verschlüsselungs-Lib).

Gibt es eine Möglichkeit den kompletten Stack Trace zu erhalten?

Danke im Voraus für Tipps!!!

12.03.2018 - 12:46 Uhr

Danke, Th69, das werde ich bald ausprobieren!
Ich hatte Lokalisierung erst mal kurz zurückgestellt, um an etwas anderes zu arbeiten.

12.03.2018 - 09:20 Uhr

Hallo, MrSparkle,

sorry, für die späte Antwort. Ich ging davon aus, dass ich bei Antworten per E-Mail benachrichtigt werde.

für die Lokalisierung genügt es, die Resourcendateien mit den lokalisierten Texten anzulegen. .NET kümmert sich um den Rest.

Heißt das, dass wenn ich eine Ressource wie "data\stringtable.en-US.restext" anlege, dass .Net an "en-US" erkennt, dass es sich um englische Übersetzungen handelt?

08.03.2018 - 08:59 Uhr

Hallo,
seit dem ich meine WPF-Applikation multilingual machen möchte und in meinem .csproj folgendes eingefügt habe:

<PropertyGroup>
	<UICulture>en-US</UICulture>
	<!-- Andere Properties... -->
</PropertyGroup>

und in meine AssemblyInfo.cs diese Anweisung:

[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]

erhalte ich regelmäßig, aber nicht immer, folgenden Fehler:

Fehlermeldung:
Die Ressource "view/usermanagementview.xaml" kann nicht gefunden werden.

Die Ressource heißt eigentlich "View/UserManagementView.xaml" und ist ein UserControl der programmatisch zur Laufzeit geladen wird, sofern gewisse Bedingungen zutreffen:

class TabItemUserManagementViewModel : Label
{
	private TabItem parent;
	private UserManagementView userManagementView = new UserManagementView();

	public TabItemUserManagementViewModel(string title, TabItem parent)
	{
		this.parent = parent;
		Content = title;
		parent.Content = userManagementView;
	}

    // Weiterer Code.
}

Weiß jemand was da vorgeht? Denn sobald ich die oben genannten Änderungen in .csproj und in AssemblyInfo.cs wieder rückgängig mache, funktioniert alles wieder zuverlässig!

Danke im Voraus!
SteffoD

01.03.2018 - 09:28 Uhr

Dieser Fehler taucht auf, wenn response null ist aber Du trotzdem versuchst auf ein Ergebnis zuzugreifen; hier der StatusCode.
Dir fehlt hier einfach die null-Prüfung.

Das habe ich auch schon gelesen, aber ich komme über SendAsync() erst gar nicht hinaus:

public static async Task<HttpResponseMessage> Send(string pathValue, HttpContent content, HttpMethod httpMethod)
{
	UriBuilder builder = QlcUriBuilder.GetUriBuilder(pathValue);
	HttpRequestMessage httpRequestMessage = new HttpRequestMessage(httpMethod, builder.Uri)
	{
		Content = content
	};
	HttpResponseMessage response = await client.SendAsync(httpRequestMessage);
	/*if (response.StatusCode == HttpStatusCode.Unauthorized)
	{
		throw new UnauthorizedException("You are not authorized to execute this operation");
	}*/
	return response; // Wenn ich hier einen Breakpoint setze, komme ich hier erst gar nicht so weit. Die Exception wird schon vorher geworfen.
}

Der zweite Punkt ist, dass ich serverseitig immer einen Status mitliefere und wenn das nur BadRequest ist.

Ich denke, das hat etwas mit dem WebRequestHandler zu tun, den ich nutze. Ich habe mal einen Bugreport gemacht: https://github.com/dotnet/corefx/issues/27549

28.02.2018 - 08:53 Uhr

Hallo,

ich habe den Fehler zuerst bei einem Integrationstest, aber jetzt nach einem Update auf eine neuere .Net Runtime auch im Debug-Modus bekommen.
Der Fehler taucht - soweit ich das nachvollziehen kann - immer dann auf, wenn _HttpClient _ etwas senden soll:

class QlcHttpTransmitter
{
	// Erbt von HttpClient. Hat lediglich ein Client-Zertifikat angefügt.
	private static readonly QlcHttpsClient client = QlcHttpsClient.Instance;

	public static async Task<HttpResponseMessage> Send(string pathValue, HttpContent content, HttpMethod httpMethod)
	{
		UriBuilder builder = QlcUriBuilder.GetUriBuilder(pathValue);
		HttpRequestMessage httpRequestMessage = new HttpRequestMessage(httpMethod, builder.Uri)
		{
			Content = content
		};
		HttpResponseMessage response = await client.SendAsync(httpRequestMessage); // Hier taucht der Fehler auf!
		if (response.StatusCode == HttpStatusCode.Unauthorized)
		{
			throw new UnauthorizedException("You are not authorized to execute this operation");
		}
		return response;
	}
}

Ich kann das nicht mit 100% Sicherheit sagen, weil Visual Studio nicht von selbst an dieser Stelle hält, sondern nur den besagten Fehler um sich wirft. Steppe ich jedoch Schritt für Schritt voran, erhalte ich den Fehler immer beim SendAsync().
Hier der vollständige Fehler:> Fehlermeldung:

Ein Ausnahmefehler des Typs "System.AccessViolationException" ist in Unbekanntes Modul. aufgetreten.
Es wurde versucht, im geschützten Speicher zu lesen oder zu schreiben. Dies ist häufig ein Hinweis darauf, dass anderer Speicher beschädigt ist.

Das Seltsame ist, dass dieser Fehler eigentlich nur bei Unmanaged Code vorkommt und ich habe an dieser Stelle kein Unmanaged Code.

Der Fehler ist wirklich zum Verzweifeln! Weiß hier jemand weiter?!

Danke im Voraus!

10.01.2018 - 15:19 Uhr

Danke, ich werde mir das mal genauer anschauen, wenn ich wieder mehr Zeit habe. 🙂

08.01.2018 - 11:30 Uhr

Hallo MrSparkle,
danke, für deine Antwort!
Wenn ich die Appl.xaml entsprechend bearbeite:

<Label Foreground="LightGray" Content="{TemplateBinding HintText}" />

dann erhalte ich folgende Fehlermeldung:> Fehlermeldung:

Fehler Member "HintText" ist nicht gültig, da er nicht über einen qualifizierenden Typnamen verfügt.

Wenn ich den Code wie zuvor belasse, dann compiliert er zwar, aber beim Debuggen ist mir aufgefallen, dass das Property HintText nie aufgerufen wird.
Irgendeine Idee? Danke im Voraus!

L. G.,
SteffoD

05.01.2018 - 08:41 Uhr

Hi an alle,

ich möchte gerne eine TextBox mit einem Hint erstellen. Leider klappt das Binding dazu nicht.
Hier die Klasse, die ich erstellt habe.

public partial class HintTextBox : TextBox
    {
        public string HintText
        {
            get { return (string)GetValue(HintTextProperty); }
            set { SetValue(HintTextProperty, value); }
        }

        public static readonly DependencyProperty HintTextProperty =
            DependencyProperty.Register("HintText", typeof(string), typeof(HintTextBox), null);
    }

Das dazugehörige XAML sieht so aus:

<TextBox x:Class="QLCClient.View.HintTextBox"
             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:QLCClient.View"
             mc:Ignorable="d">
</TextBox>

In App.xaml habe ich folgendes hinzugefügt:

<Application.Resources>
        <Style xmlns:local="clr-namespace:QLCClient.View" TargetType="{x:Type local:HintTextBox}" xmlns:sys="clr-namespace:System;assembly=mscorlib">
            <Style.Resources>
                <VisualBrush x:Key="CueBannerBrush" AlignmentX="Left" AlignmentY="Center" Stretch="None">
                    <VisualBrush.Visual>
                        <Label Foreground="LightGray" Content="{Binding HintText}" />
                    </VisualBrush.Visual>
                </VisualBrush>
            </Style.Resources>
            <Style.Triggers>
                <Trigger Property="Text" Value="{x:Static sys:String.Empty}">
                    <Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
                </Trigger>
                <Trigger Property="Text" Value="{x:Null}">
                    <Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </Application.Resources>

Folgende Zeile macht hierbei Probleme:

<Label Foreground="LightGray" Content="{Binding HintText}" />

Ändere ich die Zeile in

<Label Foreground="LightGray" Content="Search" />

dann klappt das.
Was mache ich hier falsch?

Danke im Voraus!

Grüße,
SteffoD