Wednesday, September 23, 2015

Set SVN Property Ignore with TortoiseSVN

Objects that are not checked in, were marked with questionmarks by TortoiseSVN, if icon overlay is active and functional.

If you are performing a "SVN Commit..." and "Show unversioned files" is checked, then this files will be shown.
Over time the number of files and folders can be grown and you can easily lose the overview so that needed files are not checked in. Also the risk increases that files are checked in that shouldn't (like compiled code).

For example, Visual Studio creates the folder "bin" and "obj" automatically for the compiled code. But you never want to check in the folders and their content. You can ignore the folders and their content so that they will not shown, again. To do so right click on the object to ignore and then go to "TortoiseSVN→Add to ignore list". If you choose "(recursively)" the item will be ignored in this folder and all subfolders. For files you have the choice whether all files with the same extension (*.extension) or just this particular file (file.extension) is to be ignored.

Objects that are ignored, were marked by TortoiseSVN, if icon overlay is active and functional.

Wednesday, September 2, 2015

Set SVN Property External with TortoiseSVN


An already existing project can be integrated into a new main project with the help of Subversion. This has several advantages:
  • No need to make a local copy (but be carefull with changes)
  • You can choose the version of the existing project, always the newest or fixed at some revision
  • You can use relative paths that can be predefined by the structure of the main project
If you are using a certain revision, then you prevent that changes in external project affect negatively on your project.

You can include an existing project with the property "svn:externals". This can be done at the root of the new main project.

In the context menu go to "TortoiseSVN → Properties→New...→Externals→New...". Then you have to set the "Local path" to which the external project should be checked out and the URL of the external project. If you always want to have the newest version of the external project choose "HEAD revision", otherwise choose "Revision" and set the "Peg" revision. Furthermore you can also set the "Operative" revision, if it differs.



With "SVN Update" the external projects will be checked out to the defined path.

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.