Monday, August 31, 2015

Edit Subversion Properties with TortoiseSVN

In subversion you can set properties for versioned files and folders. There are some pre-defined properties that start e.g. with "svn:". To read and write properties in TortoiseSVN, you can use the context menu. Right click on some file or folder and then go to "TortoiseSVN → Properties".
In the upcoming diolog you can see and modify the properties that exist already. With "New..." you can set new properties. Some properties can then be selected and configured directly. To obtain all properties choose "Other".
A new dialog appears. Here you can select the "Property name". In "Property value" you can set the needed value.
You can set the properties either for a folder or for one or more files. If you set it for a folder you can set the properties optionally to all subfolders and containing files. To do that check "Apply property recursively".

Saturday, July 25, 2015

Minimum column width in WPF ListView/GridView

It seems that it is not possible to set the minimum width of a column within XAML. But it can be forced withn code-behind. Laurent Bugnion has found the solution (http://geekswithblogs.net/lbugnion/archive/2008/05/06/wpf-listviewgridview-minimum-and-maximum-width-for-a-column.aspx).

The ListView is defined in the XAML part.
 
            <ListView x:Name="MyListView">
                <!-- ... -->
            <ListView.ContextMenu>

In the constructor of the code-behind part the event handler is added.
 
            ResultDataView.AddHandler(Thumb.DragDeltaEvent,
                new DragDeltaEventHandler(Thumb_DragDelta), true);

The event handler takes care that column width is not set under 20 (in this example).
 
        private void Thumb_DragDelta(object sender, DragDeltaEventArgs e)
        {
            Thumb senderAsThumb = e.OriginalSource as Thumb;
            GridViewColumnHeader header = senderAsThumb.TemplatedParent as
                                                            GridViewColumnHeader;
            if (header == null)
            {
                return;
            }
 
            if (header.Column.ActualWidth < 20)
            {
                header.Column.Width = 20;
            }
        }


Tuesday, June 23, 2015

Setting the Background of a WPF TextBox depending on Validation in a Template/Style using TemplateBinding

Recently I wanted to change the Background of a TextBox, if some own ValidationRule failed. But I couldn't get this to work. I tried several things and I gained more insights into styling and especially into styling wrong validated elements. And finally I get it to work.

If you are not familiar with WPF validation, here you can find excellent descriptions of how to use validation in WPF:

Now, I come to to initial situation.

Using ValidationRule in WPF

I had a ValidationRule, something like that.
namespace ErrorValidation
{
    public class RangeValidationRule : ValidationRule
    {
        public double Min { getset; }
        public double Max { getset; }
 
        public override ValidationResult Validate(object value,
            CultureInfo cultureInfo)
        {
            double enteredValue;
            if (double.TryParse(value.ToString(), out enteredValue))
            {
                if ((enteredValue < Min) || (enteredValue > Max))
                {
                    return new ValidationResult(false,
                      string.Format("Entered value must be in the range [{0};{1}].",
                      Min, Max));
                }
            }
            else
            {
                return new ValidationResult(false,
                    string.Format("Value '{0}' is not of type double.", value));
            }
 
            return new ValidationResult(truenull);
        }
    }
}
To get access to the ValidationRule the XML namespace is defined in the XAML.
xmlns:validation="clr-namespace:ErrorValidation"
I get access to the ValidationRule in the Window/UserControl Resources.
<validation:RangeValidationRule x:Key="RangeValidationRule" />
Now I can use the ValidationRule to validate user input.
        <TextBox Margin="12,0,12,12">
            <TextBox.Text>
                <Binding Path="InputField1"
                         UpdateSourceTrigger="PropertyChanged">
                    <Binding.ValidationRules>
                        <validation:RangeValidationRule Min="5"
                                                        Max="10" />
                    </Binding.ValidationRules>
                </Binding>
            </TextBox.Text>
        </TextBox>
The default style is used to mark user input that violates the ValidationRule.

Validation styles

So far, so good. But now I wanted to extend my existing TextBox style. If the validation failed, I wanted to change the Background of the TextBox. This was one of my not working tries.
        <Style x:Key="MyWrongTextBoxStyle"
               TargetType="{x:Type TextBox}">
            <Setter Property="Margin"
                    Value="4" />
            <Setter Property="Foreground"
                    Value="DarkBlue" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type TextBoxBase}">
                        <Border Name="Border"
                                CornerRadius="2"
                                BorderThickness="1"
                                Background="White"
                                BorderBrush="LightBlue">
                            <VisualStateManager.VisualStateGroups>
                                <VisualStateGroup x:Name="CommonStates">
                                    <VisualState x:Name="Normal" />
                                    <VisualState x:Name="Disabled">
                                        <Storyboard>
                                            <ColorAnimationUsingKeyFrames
                                                Storyboard.TargetName="Border"
                                                Storyboard.TargetProperty=
                                                "(Panel.Background).
                                                (SolidColorBrush.Color)">
                                                <EasingColorKeyFrame
                                                    KeyTime="0"
                                                    Value="LightGray" />
                                            </ColorAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </VisualState>
                                    <VisualState x:Name="ReadOnly">
                                        <Storyboard>
                                            <ColorAnimationUsingKeyFrames
                                                Storyboard.TargetName="Border"
                                                Storyboard.TargetProperty=
                                                "(Panel.Background).
                                                (SolidColorBrush.Color)">
                                                <EasingColorKeyFrame
                                                    KeyTime="0"
                                                    Value="LightBlue" />
                                            </ColorAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </VisualState>
                                    <VisualState x:Name="MouseOver" />
                                </VisualStateGroup>
                            </VisualStateManager.VisualStateGroups>
                            <ScrollViewer Margin="0"
                                          x:Name="PART_ContentHost" />
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <Setter Property="Validation.ErrorTemplate">
                <Setter.Value>
                    <ControlTemplate>
                        <StackPanel>
                            <DockPanel>
                                <AdornedElementPlaceholder x:Name="Placeholder" />
                                <TextBlock Foreground="Red"
                                           FontSize="18"
                                           Text="!" />
                            </DockPanel>
                            <StackPanel Orientation="Horizontal">
                                <TextBlock Foreground="Red"
                                           Text="The value '" />
                                <TextBlock Foreground="Red"
                                           Text="{Binding ElementName=Placeholder,
                                                      Path=AdornedElement.Text}" />
                                <TextBlock Foreground="Red"
                                           Text="' causes an error (see tooltip)" />
                            </StackPanel>
                        </StackPanel>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <Style.Triggers>
                <Trigger Property="Validation.HasError"
                         Value="True">
                    <Setter Property="ToolTip"
                            Value="{Binding RelativeSource=
                              {x:Static RelativeSource.Self},
                              Path=(Validation.Errors).CurrentItem.ErrorContent}" />
                    <Setter Property="Background"
                            Value="Orange" />
                    <Setter Property="BorderThickness"
                            Value="2" />
                    <Setter Property="BorderBrush"
                            Value="Red" />
                </Trigger>
            </Style.Triggers>
        </Style>

I tried several combinations with Validation.ErrorTemplate and Validation.HasError. But when should I use Validation.ErrorTemplate and when Validation.HasError? I have not thought much about it, until now. But the answer is not very surprising.

Validation.ErrorTemplate is used to add elements that decorate an existing element. So I cannot use it to change the Background of an existing element. But it can be used to add an image, an exclamation mark, TextBlock or something else next to the evaluated element.


Validation.HasError can be used to add a ToolTip or to change properties of an existing element.
So I should use it to change the color of the Background. But why is it not working?

The problem is how the Template style is defined. If I remove the Setter of the Template property in the Style, it is working. So I have to change the Template.

TemplateBinding

To allow changing a property of a defined Template, TemplateBinding is used. TemplateBinding is a markup extension. The properties that are set by TemplateBinding in the Template Setter can be referrenced outside the Setter of the Template. The default property values of the properties that are set by TemplateBinding can be set by other Setters. It is also possible to set the values in XAML parts that are using the Style. And now it is also possible to set the values by a Trigger, like the Background as I wanted. This is the working code that changes the Background of a TextBox in case of error.
        <Style x:Key="MyTextBoxStyle"
               TargetType="{x:Type TextBox}">
            <Setter Property="Margin"
                    Value="4" />
            <Setter Property="Foreground"
                    Value="DarkBlue" />
            <Setter Property="Background"
                    Value="White" />
            <Setter Property="BorderBrush"
                    Value="LightBlue" />
            <Setter Property="BorderThickness"
                    Value="1" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type TextBoxBase}">
                        <Border Name="Border"
                                CornerRadius="2"
                                BorderThickness="{TemplateBinding BorderThickness}"
                                Background="{TemplateBinding Background}"
                                BorderBrush="{TemplateBinding BorderBrush}">
                            <VisualStateManager.VisualStateGroups>
                                <VisualStateGroup x:Name="CommonStates">
                                    <VisualState x:Name="Normal" />
                                    <VisualState x:Name="Disabled">
                                        <Storyboard>
                                            <ColorAnimationUsingKeyFrames
                                                Storyboard.TargetName="Border"
                                                Storyboard.TargetProperty=
                                                "(Panel.Background).
                                                (SolidColorBrush.Color)">
                                                <EasingColorKeyFrame
                                                    KeyTime="0"
                                                    Value="LightGray" />
                                            </ColorAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </VisualState>
                                    <VisualState x:Name="ReadOnly">
                                        <Storyboard>
                                            <ColorAnimationUsingKeyFrames
                                                Storyboard.TargetName="Border"
                                                Storyboard.TargetProperty=
                                                "(Panel.Background).
                                                (SolidColorBrush.Color)">
                                                <EasingColorKeyFrame
                                                    KeyTime="0"
                                                    Value="LightBlue" />
                                            </ColorAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </VisualState>
                                    <VisualState x:Name="MouseOver" />
                                </VisualStateGroup>
                            </VisualStateManager.VisualStateGroups>
                            <ScrollViewer Margin="0"
                                          x:Name="PART_ContentHost" />
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <Setter Property="Validation.ErrorTemplate">
                <Setter.Value>
                    <ControlTemplate>
                        <StackPanel>
                            <DockPanel>
                                <AdornedElementPlaceholder x:Name="Placeholder" />
                                <TextBlock Foreground="Red"
                                           FontSize="18"
                                           Text="!" />
                            </DockPanel>
                            <StackPanel Orientation="Horizontal">
                                <TextBlock Foreground="Red"
                                           Text="The value '" />
                                <TextBlock Foreground="Red"
                                           Text="{Binding ElementName=Placeholder,
                                                      Path=AdornedElement.Text}" />
                                <TextBlock Foreground="Red"
                                           Text="' causes an error (see tooltip)" />
                            </StackPanel>
                        </StackPanel>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <Style.Triggers>
                <Trigger Property="Validation.HasError"
                         Value="True">
                    <Setter Property="ToolTip"
                            Value="{Binding RelativeSource=
                              {x:Static RelativeSource.Self},
                              Path=(Validation.Errors).CurrentItem.ErrorContent}" />
                    <Setter Property="Background"
                            Value="Orange" />
                    <Setter Property="BorderThickness"
                            Value="2" />
                    <Setter Property="BorderBrush"
                            Value="Red" />
                </Trigger>
            </Style.Triggers>
        </Style>
And this is the result.


Wednesday, May 13, 2015

Audino - Arduino MP3-Player (18) - PC-Software

Der Audino kann nun verwendet werden. Dazu werden auf der SD-Karte 10 Ordner mit den Namen 0, 1, 2, 3, 4, 5, 6, 7, 8 und 9 angelegt. In den Ordnern 1 bis 9 können nun MP3-Dateien kopiert werden. Die Dateinamen werden ebenfalls durchnummeriert (1.mp3, 2.mp3, 3.mp3, 4.mp3, ...). Die MP3-Dateien sollten dabei im Mono-Format vorliegen, da nur ein Kanal verwendet wird.

Um das Kopieren zu erleichtern, habe ich eine PC-Software erstellt, mit der die Abspiellisten geplant und erzeugt werden können.

Über "Select SD card" wird der Speicherort ausgewählt. dies sollte die SD-Karte sein. Wurden hier schon mit der PC-Software MP3-Tracks kopiert, so werden die gemachten Einträge ausgelesen, sodass diese bearbeitet werden können. Über "Copy to SD card" werden die MP3-Tracks auf die SD-Karte kopiert und umbenannt. Die MP3-Tracks sollten bereits im Mono-Format vorliegen. Mit "Reset" werden alle Einträge gelöscht.


In der Übersicht werden die 9 Knöpfe angezeigt. In den eckigen Klammern steht die Anzahl der Tracks gefolgt von der Spieldauer. Unten links steht die Gesamtanzahl der Tracks und die Gesamtspieldauer. Drückt man auf einen der 9 Knöpfe, kommt man in die Ansicht der hinzugefügten MP3-Tracks. Hier können weitere Tracks hinzugefügt oder wieder rausgelöscht werden.


Bei Interesse kann ich die PC-Software gerne zur Verfügung stellen.

Damit wäre das Projekt "Audino" nun endgültig abgeschlossen


Weitere Blogeinträge

  1. Auswahl der Komponenten
  2. Das Entwicklungsbrett
  3. Das erste Einschalten
  4. Die Entwicklungsumgebung
  5. Knöpfe (digital)
  6. Mehrere Knöpfe (digital)
  7. Mehrere Knöpfe (analog)
  8. Potentiometer
  9. Das MP3 Shield
  10. Auswahl der Komponenten 2
  11. Auswahl der Komponenten (Zusammenfassung) 
  12. Punkt-Streifenrasterplatine und Knöpfe
  13. Punkt-Streifenrasterplatine und weitere Komponenten
  14. Das Gehäuse
  15. Sketch 1 (setup-Methode)
  16. Sketch 2 (loop-Methode)
  17. Sketch 3 (Der komplette Code)
  18. PC-Software