Biggle's Blog

Web- und Software Development

by Mario Priebe

WebSequenceDiagrams API mit .NET

Heute bin ich durch einen Tweet auf websequencediagrams aufmerksam geworden. Mit websequencediagrams kann man sich über eine einfache Textnotation ein SequenzDiagramm in verschiedenen Styles erstellen lassen.

Die Applikation bietet aber auch eine Schnittstelle die es einem ermöglicht mit .NET ein solches Diagramm zu erstellen.

Folgendes CodeSnippet soll zeigen wie:

1 public void SaveSequenceDiagram(string data, string outFile, SequenceStyle style, SequenceOutputFormat outputFormat) 2 { 3 var request = WebRequest.Create("http://www.websequencediagrams.com"); 4 request.Method = "POST"; 5 6 string postData = string.Format("style={0}&format={1}&message={2}", style, outputFormat, HttpUtility.UrlEncode(data, Encoding.UTF8)); 7 8 byte[] byteArray = Encoding.UTF8.GetBytes(postData); 9 request.ContentType = "application/x-www-form-urlencoded"; 10 request.ContentLength = byteArray.Length; 11 12 //because error: The remote server returned an error: (417) Expectation Failed. 13 System.Net.ServicePointManager.Expect100Continue = false; 14 15 Stream dataStream = request.GetRequestStream(); 16 dataStream.Write(byteArray, 0, byteArray.Length); 17 dataStream.Close(); 18 19 dataStream = request.GetResponse().GetResponseStream(); 20 if (dataStream == null) return; 21 22 using (var reader = new StreamReader(dataStream)) 23 { 24 string responseFromServer = reader.ReadToEnd(); 25 var image = responseFromServer.Substring(12, 9); 26 27 using (var webClient = new WebClient()) 28 { 29 byte[] resp = webClient.DownloadData(string.Format("http://www.websequencediagrams.com?{0}={1}", outputFormat, image)); 30 using (var fileStream = new FileStream(outFile, FileMode.OpenOrCreate)) 31 { 32 fileStream.Write(resp, 0, resp.Length); 33 } 34 } 35 } 36 37 dataStream.Close(); 38 }

1 public enum SequenceOutputFormat 2 { 3 img, 4 pdf, 5 png, 6 svg 7 }

1 public enum SequenceStyle 2 { 3 @default, 4 earth, 5 modernblue, 6 mscgen, 7 omegapple, 8 qsd, 9 rose, 10 roundgreen, 11 napkin, 12 }

Aufgerufen wird das ganze wie folgt:

1 SaveSequenceDiagram("Alice->Bob: Authentication Request\nactivate Bob\nBob->Alice: Authentication Response\ndeactivate Bob", "out.svg", 2 SequenceStyle.roundgreen, SequenceOutputFormat.svg);

Beim Aufruf an den Dienst hab ich zu Anfang immer folgende Fehlermeldung bekommen “The remote server returned an error: (417) Expectation Failed.” Die Problemlösung habe ich nach etwas googlen, beim Gordon finden können. Danke nochmal an dieser Stelle.

Viel Spaß beim entwickeln : )

by Mario Priebe

Prüfen ob ein String eine Guid ist

Es gibt jede Menge Ansätze, um zu prüfen ob ein String eine Guid ist. Zum einen ist es möglich, den String mit RegEx zu prüfen:

1
2
3
4
5
6
using System.Text.RegularExpressions;
...
private bool IsStringValidGuid(string s)
{
    return string.IsNullOrEmpty(s) ? false : new Regex(@"^(\{{0,1}([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}\}{0,1})$").IsMatch(s);
}

Als ExtensionMethod könnte das wie folgt aussehen:

1
2
3
4
5
6
using System.Text.RegularExpressions;
...
public static bool IsStringValidGuid(this string s)
{
    return string.IsNullOrEmpty(s) ? false : new Regex(@"^(\{{0,1}([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}\}{0,1})$").IsMatch(s);
}

Zum anderen kann man sich jeden Character in dem String anschauen und prüfen ob dieser im Hexadezimalsystem vorkommt.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/// <summary>
/// Prueft ob der uebergebene String eine Guid ist.
/// </summary>
/// <param name="s">string</param>
/// <returns>bool</returns>
public bool IsStringValidGuid(string s)
{
    int hexchars = 0;
    foreach (char c in s)
    {
        if (IsValidHexChar(c))
            hexchars++;
    }
    return hexchars == 32;
}
private bool IsValidHexChar(char hexChar)
{
    return (hexChar >= 0x30 && hexChar <= 0x39) //IsValidHexDigit
        || (hexChar >= 0x61 && hexChar <= 0x66) //IsValidLowerHexLetter
        || (hexChar >= 0x41 && hexChar <= 0x46); //IsValidUpperHexLetter
}

Als ExtensionMethod:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/// <summary>
/// Prueft ob der uebergebene String eine Guid ist.
/// </summary>
/// <param name="s">string</param>
/// <returns>bool</returns>
public static bool IsStringValidGuid(this string s)
{
    int hexchars = 0;
    foreach (char c in s)
    {
        if (IsValidHexChar(c))
            hexchars++;
    }
    return hexchars == 32;
}
private bool IsValidHexChar(char hexChar)
{
    return (hexChar >= 0x30 && hexChar <= 0x39) //IsValidHexDigit
        || (hexChar >= 0x61 && hexChar <= 0x66) //IsValidLowerHexLetter
        || (hexChar >= 0x41 && hexChar <= 0x46); //IsValidUpperHexLetter
}

Die RegEx-Version finde ich eleganter (da Einzeiler), jedoch die Zeichen einzeln zu prüfen, finde ich für das Verständnis besser.

Wie auch immer, funktionieren werden sicher noch mehr Wege…
In diesem Sinne, viel Spaß beim entwickeln : )

by Mario Priebe

ToolTip an einem “disabled Button” – XAML Quicky

Stellt man einen Button auf “disabled”, wird leider kein Tooltip mehr angezeigt. Möchte man dem entgegenwirken, verwendet man die Methode ShowOnDisabled am ToolTipService:

1
<Button Content="Hier klicken" ToolTipService.ShowOnDisabled="True" IsEnabled="False" ToolTip="Hier klicken"/>

Viel Spaß beim entwickeln : )


by Mario Priebe

TextTrimming – XAML Quicky

Im XAML hat man die Möchglichkeit den Text zu kürzen, wenn dieser länger ist, als die Oberfläche es zulässt.

Man kann bestimmen, ob man nach einem Wort (WordEllipsis) und nach einem Buchstaben (CharacterEllipsis) den Text abtrennt. 3 Punkte (…) zeigen dem Benutzer an, das hier weiterer Text hinterlegt ist.

1
2
<TextBlock  Name="sampleTextBlock" TextTrimming="WordEllipsis"  TextWrapping="NoWrap" 
                    Text="Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet."/>

Viel Spaß beim entwickeln : )

by Mario Priebe

Doppelklick im DataGrid abfangen – WPF Quicky

Möchte man auf den Klick eines Datensatzes  in einem WPF DataGrid reagieren, so kann man folgenden Code dazu verwenden:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private void dataGrid_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
    DependencyObject dep = (DependencyObject)e.OriginalSource;
 
    while ((dep != null) && !(dep is DataGridRow))
    {
        dep = VisualTreeHelper.GetParent(dep);
    }
 
    if (dep == null)
        return;
 
    if (dep is DataGridRow)
    {
        DataGridRow dataGridRow = dep as DataGridRow;
        //tu was
    }
}

Den Klick auf denDataGrid-ColumnHeader oder einer DataGrid-Zelle kann mit der selben Methode behandelt werden. Hier wird einfach die Abfrage mit in das if-Statement aufgenommen und im Rumpf dementsprechend behandelt.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
private void dataGrid_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
    DependencyObject dep = (DependencyObject)e.OriginalSource;
 
    while ((dep != null) && !(dep is DataGridRow) && !(dep is DataGridColumnHeader) && !(dep is DataGridCell))
    {
        dep = VisualTreeHelper.GetParent(dep);
    }
 
    if (dep == null)
        return;
 
    if (dep is DataGridRow)
    {
        DataGridRow dataGridRow = dep as DataGridRow;
        //tu was
    }
 
    if (dep is DataGridColumnHeader)
    {
        DataGridColumnHeader columnHeader = dep as DataGridColumnHeader;
        //tu was
    }
 
    if (dep is DataGridCell)
    {
        DataGridCell cell = dep as DataGridCell;
        //tu was
    }
 
}


Viel Spaß beim entwickeln : )

by Mario Priebe

Bedingte Formatierung im Datagrid – WPF Quicky

Die Frage auf Codekicker lautete:

Wie kann ich in einem DataGrid eine Zelle je nach Inhalt formatieren? So wie die Bedingte Formatierung in Excel oder Access, also rot bei negativen Werten und grün bei positiven Werten. Hab schon mein Glück mit einem Converter versucht, aber das klappt irgendwie nicht.

Ich habe dazu einen Converter geschrieben, der den Wert entgegen nimmt, diesen auf kleiner 0 prüft und das Resultat als Brush für den Hintergrund zurück gibt. Ist der Wert kleiner 0 wird grün, ist der Wert größer 0 wir rot zurück gegeben.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
    if (value.ToString() == String.Empty)
        return null;
 
    decimal val = decimal.Parse(value.ToString());
 
    return (val < 0) ? Brushes.Red : Brushes.Green;
}
 
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
    return value;
}
}

Im XAML muss in der Windows Resource der Converter referenziert werden:

1
2
3
<Window.Resources>
    <Converters:SignedUnsignedConverter x:Key="SignedUnsigned" />
</Window.Resources>

Das DataGrid verwendet den Converter wie folgt:

1
2
3
4
5
6
7
8
9
10
11
12
<DataGrid Name="dataGrid" AutoGenerateColumns="False" MouseDoubleClick="dataGrid_MouseDoubleClick">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Name" Binding="{Binding Name}" />
        <DataGridTemplateColumn Header="Price">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Price}" Background="{Binding Price, Converter={StaticResource SignedUnsigned}}" />
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
    </DataGrid.Columns>
</DataGrid>

Auch in einer TextBox kann der Converter verwendet werden:

1
<TextBox Name="textBox" Background="{Binding ElementName=textBox, Path=Text, Converter={StaticResource SignedUnsigned}}"/>


Viel Spaß beim entwickeln : )