Biggle's Blog

Web- und Software Development

by Mario Binder

MultiBinding die Zweite

Ich hatte schon vor einiger Zeit gezeigt (puh, schon wieder 1 1/2 Jahre her..) , wie man im XAML ein MultiBinding implementiert. Nun stand ich vor einem Problem, das ich im XAML ein paar Elemente definiere und im Code weitere Elemente zur Laufzeit hinzufüge. Diese Elemente wollte ich nun vernünftig zusammenbringen.

Im Code benötige ich eine Slider-Property und eine Property Namens “Caption”, welche einen Text halten soll. Im Xaml habe ich ein TextBlock-Element, welcher den Inhalt der Caption-Property und den aktuellen Wert des Sliders anzeigen soll.

1
2
public string Caption { get; set; }
public Slider Slider { get; set; }
1
<TextBlock Grid.ColumnSpan="3" Name="CaptionTxtBlock" />

Der Slider, welcher von aussen gesetzt wird, bekommt im “Loading” noch ein paar Eigenschaften und die Position im UserControl mit:

1
2
3
4
Slider.Name = "slider";
Slider.SetValue(Grid.RowProperty, 1);
Slider.SetValue(Grid.ColumnProperty, 1);
SliderGrid.Children.Add(Slider);

Anschliessend baue ich mir ein MultiBinding-Objekt, dass nun die beiden benötigen Properties an meiner TextProperty des TextBlockes bindet und entsprechend formatiert ausgibt:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
MultiBinding mb = new MultiBinding()
{
    Mode = BindingMode.TwoWay,
    UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,
    StringFormat = "{0} ({1:00} %)"
};
 
Binding sliderBinding = new Binding()
{
    Source = Slider,
    Path = new PropertyPath("Value")
};
 
Binding captionBinding = new Binding()
{
    Source = this,
    Path = new PropertyPath("Caption")
};
 
mb.Bindings.Add(captionBinding);
mb.Bindings.Add(sliderBinding);
 
BindingOperations.SetBinding(CaptionTxtBlock, TextBlock.TextProperty, mb);

Und so sieht das ganze dann aus:

Download Code

Viel Spaß beim entwickeln : )

by Mario Binder

Text innerhalb eines TextBlock-Controls formatieren – XAML

Um einen Text innerhalb einer Textbox zu formatieren, steht einem die Klasse Run zur Verfügung. Run ist ein Element für fortlaufenden Inhalt auf Inlineebene, das formatierten oder unformatierten Lauftext enthalten kann.

1
2
3
4
<TextBlock FontSize="28" TextWrapping="Wrap">
    Hier steht <Run Foreground="Red">Text</Run> der
    <Run FontWeight="Bold" FontStyle="Italic" Foreground="Cyan" FontSize="38" TextDecorations="Underline">verschiedene Formate</Run> darstellt.
</TextBlock>

Einen Zeilenumbruch innerhalb eines Textblocks erreicht man mit

<LineBreak />

Bei einem Hyperlink kann diese Methode auch angewendet werden. (In Silverlight HyperlinkButton)

1
2
3
4
5
6
7
<TextBlock TextWrapping="Wrap">            
    <Hyperlink TextDecorations="None" NavigateUri="http://www.biggle.de">
        <Italic>Hier</Italic> <Bold>steht</Bold> ein <Underline>Hyperlink</Underline>                 
        <LineBreak />      
            über mehrere <Run Foreground="Red">Zeilen</Run>.
    </Hyperlink>
</TextBlock>

Im Hyperlinkbeispiel sieht man auch, wie man den Text kursiv,  fett geschrieben und unterstrichen, noch formatieren kann.

Selbst Bilder können so in einem TextBlock mit dargestellt werden:

1
2
3
4
5
<TextBlock>
    Das bin ich
    <LineBreak />
    <Image Source="/Images/IMG_6911_small.jpg" Width="50" />
</TextBlock>

Es ist auch möglich, innerhalb des Textblock-Controls Werte aus einem Binding heraus darzustellen:

1
2
3
4
5
6
7
8
9
<TextBlock DataContext="{Binding Order}" TextWrapping="Wrap">
    <Run TextDecorations="Underline">Ihre Bestellung</Run>
    <LineBreak />
    <Run>Produkt:</Run>
    <TextBlock Text="{Binding productName}" />
    <Run>(</Run>
        <TextBlock Text="{Binding quantity}" />
    <Run>)</Run>
</TextBlock>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public partial class MainWindow : Window
{
    public Order Order { get; set; }
 
    public MainWindow()
    {
        InitializeComponent();
        LoadOrders();
    }  
    private void LoadOrders()
    {
        Order = new Order();
        Order.productName = "Mountainbike";
        Order.quantity = 1;
 
        this.DataContext = this;
    }
}


Viel Spaß beim entwickeln : )

by Mario Binder

Eigenes Hyperlink Control – XAML

Der eine oder andere hat dies sicher schon bemerkt. Wenn man im XAML ein Hyperlink Element einsetzt und NavigateUri mit der entsprechenden Adresse definiert, könnte man annehmen, dass das ausreicht um den Link aufzurufen. Doch leider ist dem nicht so.

Man könnte aber sein eigenes Control schreiben, welches diese Funktionalität beinhaltet.

Dazu fügt man ein neues UserControl hinzu und benennt dieses “Link“. Dieses UserControl muss nun so abgeändert werden, dass dieses von Hyperlink ableitet. Im Xaml muss der Knoten UserControl in Hyperlink umbenannt und im code-behind muss das UserControl auch dahingehend abgeändert werden.

1
2
3
4
5
<Hyperlink x:Class="WPFSpielwiese.Link"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
 
</Hyperlink>

Nun registrieren wir uns am Event “RequestNavigate” und implementieren einen einfachen Process.Start um die URL aus NavigateUri aufzurufen. Die Fehlerbehandlung lass ich an dieser Stelle mal weg.

1
2
3
4
5
6
7
8
9
10
11
12
13
public partial class Link : Hyperlink
{
    public Link()
    {
        InitializeComponent();
        this.RequestNavigate += new RequestNavigateEventHandler(Link_RequestNavigate);
    }
 
    void Link_RequestNavigate(object sender, RequestNavigateEventArgs e)
    {
        Process.Start(this.NavigateUri.ToString());
    }
}

Eingesetzt wird das ganze dann wie folgt:

1
2
3
4
5
xmlns:mp="clr-namespace:WPFSpielwiese"
..
<TextBlock>
    <mp:Link NavigateUri="http://www.biggle.de">Biggle's Blog</mp:Link>
</TextBlock>


Viel Spaß beim entwickeln : )

by Mario Binder

Verwenden von SoundPlayerAction und SoundPlayer- WPF Quicky

Sounds mit WPF abspielen kann man über der Klasse SoundPlayerAction. Implementiert werden kann das ganze sowohl im Xaml als auch im Code.

Im Xaml:

1
2
3
4
5
6
7
<Button Content="Play Sound">
    <Button.Triggers>
        <EventTrigger RoutedEvent="Button.Click">
            <SoundPlayerAction Source="pack://siteoforigin:,,,/Media/Windows Exclamation.wav" />
        </EventTrigger>
    </Button.Triggers>
</Button>

Im Xaml muss der Pfad zur Datei mit absoluter Angabe oder als siteoforgin-Datei (Inhalt, immer kopieren) angeben werden.

Im Code ist die Instanzierung der Klasse SoundPlayer und der Methodenaufruf Play ausreichend:

1
2
SoundPlayer sp = new SoundPlayer("Media/Windows Exclamation.wav");
sp.Play();

Auch hier muss das entsprechende Mediafile über den Eigenschaften immer in das Ausgabeverzeichnis kopiert werden.

Die Mediadatei kann über ein Dateipfad, einer Url und von einem Stream aus geladen werden.

Ergänzend sollte ich noch erwähnen, das die Klasse SoundPlayer, welche im Code implementiert wird, mehrere Methoden zum Abspielen von Sounddateien hat. Zum einen die genannte Play, welche das File asynchron abspielt. Die Methode PlaySync hingegen spielt das ganze synchron ab und mit PlayLooping wird das Mediafile in einer Endlosschleife abgespielt. Über der Methode Stop wird das Abspielen abgebrochen.

Standardmässig wird das File erst beim ersten Abspielen geladen, über die Methoden Load und LoadAsync kann dieser Vorgang im Voraus gemacht werden. Das Event LoadCompleted wird gefeuert, wenn das File geladen wurde.

Abgespielt werden können mit den Klassen SoundPlayerAction und SoundPlayer lediglich *.wav Dateien.

Viel Spaß beim entwickeln : )

by Mario Binder

Escape-Sequenz in XAML

Möchte man im XAML in einem Attribut z.B. Text oder Content geschweifte Klammern verwenden,

muss man diese entsprechend escapen. Hier verwendet man vor dem eigentlichen Inhalt zwei geschweifte Klammern {}

<TextBlock Text="{}{Welt}" />

Wird der Text mit weiteren Text außerhalb der geschweiften Klammern kombiniert, macht XAML das automatisch

<TextBlock Text="Hallo {Welt}" />

by Mario Binder

WPF Tabbing GUI

Für kleine Applikationen mit eine paar Buttons muss man immer wieder ein Menü und einzelne Seiten neu implementieren, oder aber man hat sich eine kleines Framework gebaut, der einem diese Arbeit abnimmt.

Für solche Zwecke, habe ich mich für die zweite Variante entschieden, die ich Euch natürlich nicht vorenthalten möchte. Nix dolles, aber für Übungszwecke ganz gut geworden : ) Ich nenne das Teil einfach mal WPF Tabbing GUI. Mit WPF Tabbing GUI kann man mit wenigen Klicks einen kleinen Applikationsrahmen zusammenbauen. Über der Konfiguration “klickt” man sich die Navigations-Items mit den dazugehörigen Pages und Icons zusammen und definiert ob man das Menu oben, unten, rechts oder links haben möchte. Anschließend muss man nur noch für jede Page (View) ein ViewModel und ein Model implementieren und fertig.

Das Simple-WPF-GUI-Framework besteht lediglich aus ein TabControl, etwas Styling  und ein bissle Konfiguration. Ich möchte jedoch anmerken, das die GUI ein ausbaufähiger Entwurf ist, bei dem noch eine Menge verbessert und erweitert werden kann. Nicht das mir da nachher Beschwerden kommen :p Als Entwurfsmuster habe ich im übrigen MVVM gewählt, da ich hier denke, die meisten unter Euch verwenden dieses Pattern.

Die Technische Umsetzung und Fragen zur Verwendung findet man direkt auf der Projektseite.

Also einfach mal ausprobieren, kostet nix : )