MVVM, Silverlight, WPF

ViewModel 1st Child Container PRISM Navigation

I have recently just started work on a greenfield WPF project using PRISM 4. When I started I knew that we would be used a workspace driven design and that I wanted to go VM first route, and that I wanted to make use of PRISMs navigation API.

I was also pretty keen to try and use child IOC containers for my workspaces where possible, such that the life cycle of the child container could be coupled to the VM that would be shown for a workspace. That way when the VM was closed the child container and all its dependencies would also be cleaned up.

So I had a bit of a play around with PRISM and managed to get that work out quite nicely. If this sounds like it would be of use to you, you can learn more by reading the full article, which is available right here:

http://www.codeproject.com/Articles/640573/ViewModel-1st-Child-Container-PRISM-Navigation

CodeProject, Current Work, Silverlight

Double Whammy

So I just got up this morning and turned on my PC and checked my emails, and low and behold I got some very good news. One of my recent Task Parallel Library articles http://www.codeproject.com/KB/cs/TPL1.aspx did very well in the monthly codeproject competitions, it won

  • Best overall article for the month
  • Best C# article for the month

Cool

Cinch, MVVM, Silverlight, WPF

CinchV2 and PRISM 4 Interoperability

I have been working on 2 small demo apps using my CinchV2 MVVM framework code used in conjunction with the latest PRISM 4 release (which now uses MEF).

I am actually pretty happy with the results of how easy these 2 frameworks work together, it is almost seamless.

So if you are a fan of PRISM features such as Regions/Modules etc etc, but want some of the goodness from Cinch like the ViewModel base classes and UI Services, then the article I have made to cover these demo apps could be for you.

The url to the article is right here : http://www.codeproject.com/KB/WPF/CinchV2AndPRISM4.aspx

C#, MVVM, Silverlight, WPF

Look At AOP : Getting Rid Of INPC Using Aspects

Some of you may know me, and know that I am quite into WPF, some of you may even be into WPF yourselves and come to my blog to see what posts I have here to do with WPF.

Well I just released a new article all about Aspect Orientated Programming (AOP).

I looked at 4 different AOP frameworks:

  • Castle
  • Unity
  • PostSharp
  • LinFu.AOP

Now as a WPF developer I use the INotifyPropertyChanged interface (INPC) an awful lot.

I have to say a lot of the time I am merely checking the new value does not equal current value and then calling the INotifyPropertyChanged interfaces PropertyChanged event. Not all the time mind, there are cases where something different happens in the setter….but 80% of it is bulk standard, check property and call PropertyChanged  changed event.

Which looks like this typically:

public class MainWindowViewModel : INotifyPropertyChanged
{

    private int someProperty;
    public int SomeProperty
    {
       get { return someProperty; }
       set
       {
         if (someProperty != value
         {
        someProperty=value;
        RaisePropertyChanged("SomeProperty");
         }
       }
    }


    public event PropertyChangedEventHandler PropertyChanged;

    protected void RaisePropertyChanged(string propertyName)
    {
       if (PropertyChanged != null)
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

}

 

Now I got thinking if we could use AOP to come up with something like this, where we use some special attribute to mark standard auto properties as INPC, where the AOP framework would fire the INPC PropertyChanged event whenever a property marked up with one of these attributes was set.

public class MainWindowViewModel : INotifyPropertyChanged
{

    [INPCAttribute]
    public virtual string DummyProp1 { get; set; }

    [INPCAttribute]
    public virtual string DummyProp2 { get; set; }


    public event PropertyChangedEventHandler PropertyChanged;

    protected void RaisePropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }Which got me thinking even more, perhaps if an AOP framework could do that, it may even be able to implement the entire INotifyPropertyChanged interface for me to, which would lead to classes like this:

public class DummyModel
{
    [AddINPCAttribute]
    public virtual string DummyModelProp1 { get; set; }

    [AddINPCAttribute]
    public virtual string DummyModelProp2 { get; set; }

    public virtual string DummyModelProp3 { get; set; }
}

 

The good news is that I did manage to achieve these results, and if you are interested you should read the entire article using this link:

http://www.codeproject.com/KB/miscctrl/Aspects.aspx

Please do not forget to vote…….thanks

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

CodeProject, Silverlight, WPF

Styling A ContextMenu In Expression Blend

The other day we had a requirement to style a ContextMenu for our large WPF app. Now this sounds easy enough to do, and there are even some pointer on a Microsoft site which show you the alleged Styles applied to the standard controls, for the ContextMenu though, the example on the Microsoft site which is as follows:

<Style TargetType="ContextMenu">
  <Setter Property="SnapsToDevicePixels" Value="True"/>
  <Setter Property="OverridesDefaultStyle" Value="True"/>
  <Setter Property="Grid.IsSharedSizeScope" Value="true"/>
  <Setter Property="HasDropShadow" Value="True"/>
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="ContextMenu">
        <Border 
          Name="Border"
          Background="{StaticResource WindowBackgroundBrush}"
          BorderBrush="{StaticResource SolidBorderBrush}"
          BorderThickness="1" >
          <StackPanel IsItemsHost="True"
                      KeyboardNavigation.DirectionalNavigation="Cycle"/>
        </Border>
        <ControlTemplate.Triggers>
          <Trigger Property="HasDropShadow" Value="true">
            <Setter TargetName="Border" Property="Padding" Value="0,3,0,3"/>
            <Setter TargetName="Border" Property="CornerRadius" Value="4"/>
          </Trigger>
        </ControlTemplate.Triggers>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

Turned out to be way wrong, you can clearly see that the screen shot below which uses the standard ContextMenu with no additional styling has a ScrollViewer to present items that do not fit in a certain amount of space. There clearly is no ScrollViewer in the Microsoft example shown above.

https://i0.wp.com/dl.dropbox.com/u/2600965/Blogposts/2010/11/ContextMenu/1.png

So I thought ok, so I need to Style a ContextMenu myself, fine. How I would normally tackle this in Expression Blend is to place some control on the work surface, right click, and just  choose to edit the current Template. This is shown below, where I will edit a Button Template.

https://i0.wp.com/dl.dropbox.com/u/2600965/Blogposts/2010/11/ContextMenu/2.png

Thing is this approach does not work for ContextMenu at all. mmmm So what can you do. Well luckily Expression Blend is awesome enough to cope with this, so what you do is as follows assuming you have a ContextMenu (or even have a dummy one created just so you can test the Styling)

I have this dummy one created:

<Grid x:Name="LayoutRoot" Background="CornflowerBlue">
    <Grid.ContextMenu>
        <ContextMenu>
            <MenuItem Header="MenuItem"/>
            <MenuItem Header="MenuItem"/>
            <MenuItem Header="MenuItem"/>
            <MenuItem Header="MenuItem"/>
            ....
            ....
            ....
            ....
            <MenuItem Header="MenuItem"/>
            <MenuItem Header="MenuItem"/>
            <MenuItem Header="MenuItem"/>
        </ContextMenu>
    </Grid.ContextMenu>
</Grid>

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

So lets assume you have a similar setup. So how can we get into what the ContextMenu style looks like. Well in Blend find you control that has the ContextMenu (real or dummy one) applied, in the VisualTree in Blend. For me that is the Grid called “LayoutRoot”. So here is me doing that

https://i0.wp.com/dl.dropbox.com/u/2600965/Blogposts/2010/11/ContextMenu/3.png

Next I look at the selected Grid (“LayoutRoot”) properties, and I find its ContextMenu property, which is under the Miscellaneous group.

https://i0.wp.com/dl.dropbox.com/u/2600965/Blogposts/2010/11/ContextMenu/4.png

Now you can expand the ContextMenu as I have above, and scrolldown until you find the ContextMenu Style property.

https://i0.wp.com/dl.dropbox.com/u/2600965/Blogposts/2010/11/ContextMenu/6.png

Then what you can do is click on the small rectangle on the right, and select the “Convert to New Resource” option as shown below

https://i0.wp.com/dl.dropbox.com/u/2600965/Blogposts/2010/11/ContextMenu/6.png

Ok so now what we get if we go to our XAML is a new ContextMenu style that looks something like this, which Expression Blend just generated for us

<!-- This is what Blend produced when you let it create 
     a local resource for you for the ContextMenu -->
<Style x:Key="ContextMenuStyle1" 
    TargetType="{x:Type ContextMenu}">
    <Setter Property="Background" 
        Value="{DynamicResource MenuBackgroundBrush}"/>
    <Setter Property="BorderThickness" 
        Value="1"/>
    <Setter Property="BorderBrush" 
        Value="{DynamicResource WindowBorderBrush}"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ContextMenu}">
                <Border Uid="Border_93">
                    <Border.Style>
                        <Style TargetType="{x:Type Border}">
                            <Setter Property="Tag" 
                                Value="{DynamicResource 
                                    {x:Static SystemParameters.DropShadowKey}}"/>
                            <Style.Triggers>
                                <DataTrigger 
                                        Binding="{Binding Tag, 
                                            RelativeSource={RelativeSource Self}}" 
                                        Value="True">
                                    <Setter Property="Background" 
                                        Value="Transparent"/>
                                    <Setter Property="Padding" 
                                        Value="0,0,5,5"/>
                                    <Setter Property="Effect">
                                        <Setter.Value>
                                            <DropShadowEffect 
                                                BlurRadius="4" 
                                                Opacity="0.8" 
                                                ShadowDepth="1"/>
                                        </Setter.Value>
                                    </Setter>
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </Border.Style>
                    <Border BorderBrush="{TemplateBinding BorderBrush}" 
                            BorderThickness="{TemplateBinding BorderThickness}" 
                            Background="{TemplateBinding Background}" 
                            Uid="Border_50">
                        <ScrollViewer CanContentScroll="True" 
                            Style="{DynamicResource {ComponentResourceKey ResourceId=MenuScrollViewer, 
                                    TypeInTargetAssembly={x:Type FrameworkElement}}}" 
                                    Uid="ScrollViewer_9">
                            <ItemsPresenter 
                                KeyboardNavigation.DirectionalNavigation="Cycle" 
                                Margin="{TemplateBinding Padding}" 
                                SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" 
                                Uid="ItemsPresenter_5"/>
                        </ScrollViewer>
                    </Border>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

 

Ok so that is what the ContextMenu looks like by default. But what I wanted to do was swap out the standard look and feel of the ContextMenu (not the MenuItem controls they are styled separately), and the look of the Up/Down arrows it obviously has in its Template. So how about that then.

Well looking into it, I could see a ScrollViewer that is declared like this, which seemed to be the key:

<ScrollViewer CanContentScroll="True" 
    Style="{DynamicResource {ComponentResourceKey ResourceId=MenuScrollViewer, 
            TypeInTargetAssembly={x:Type FrameworkElement}}}" 
            Uid="ScrollViewer_9">

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

So all that I really need to do then was create a new Style for the ScrollViewer using that ComponentResourceKey, which I did and here is all the relevant XAML for that.

<!-- These are the extras that you have to create to get your own ScrollViewer in for a custom ContextMenu
     ScrollViewer -->
<MenuScrollingVisibilityConverter x:Key="MenuScrollingVisibilityConverter" />

    <Style x:Key="MenuScrollButton"
           BasedOn="{x:Null}"
           TargetType="{x:Type RepeatButton}">
        <Setter Property="ClickMode"
                Value="Hover" />
        <Setter Property="MinWidth"
                Value="0" />
        <Setter Property="MinHeight"
                Value="0" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type RepeatButton}">
                    <DockPanel SnapsToDevicePixels="true" Width="Auto" 
                           Height="30"
                               Background="CornflowerBlue">
                        <Rectangle x:Name="R1"
                                   Width="2"
                                   Fill="DarkBlue"
                                   DockPanel.Dock="Right" />
                        <Rectangle x:Name="B1"
                                   Height="2"
                                   Fill="DarkBlue"
                                   DockPanel.Dock="Bottom" />
                        <Rectangle x:Name="L1"
                                   Width="2"
                                   Fill="DarkBlue"
                                   DockPanel.Dock="Left" />
                        <Rectangle x:Name="T1"
                                   Height="2"
                                   Fill="DarkBlue"
                                   DockPanel.Dock="Top" />
                        <ContentPresenter HorizontalAlignment="Center"
                                          Margin="2,2,2,2"
                                          x:Name="ContentContainer"
                                          VerticalAlignment="Center" />
                    </DockPanel>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>        



      <Geometry x:Key="UpArrow">M 0,4 L 3.5,0 L 7,4 Z</Geometry>
    <Geometry x:Key="DownArrow">M 0,0 L 3.5,4 L 7,0 Z</Geometry>

    <Style x:Key="{ComponentResourceKey ResourceId=MenuScrollViewer, 
        TypeInTargetAssembly={x:Type FrameworkElement}}"
           BasedOn="{x:Null}"
           TargetType="{x:Type ScrollViewer}">
        <Setter Property="HorizontalScrollBarVisibility"
                Value="Hidden" />
        <Setter Property="VerticalScrollBarVisibility"
                Value="Auto" />
        <Setter Property="MaxHeight"
                Value="200" />        
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ScrollViewer}">
                    <Grid SnapsToDevicePixels="true">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="*" />
                            <RowDefinition Height="Auto" />
                        </Grid.RowDefinitions>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*" />
                        </Grid.ColumnDefinitions>
                        <Border Grid.Column="0"
                                Grid.Row="1">
                            <ScrollContentPresenter Margin="{TemplateBinding Padding}" />
                        </Border>
                        <RepeatButton Focusable="false"
                                      Style="{StaticResource MenuScrollButton}"
                                      Grid.Column="0"
                                      Grid.Row="0"
                                      Command="{x:Static ScrollBar.LineUpCommand}"
                                      CommandTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}">
                            <RepeatButton.Visibility>
                                <MultiBinding FallbackValue="Visibility.Collapsed"
                                              Converter="{StaticResource MenuScrollingVisibilityConverter}"
                                              ConverterParameter="0">
                                    <Binding Path="ComputedVerticalScrollBarVisibility"
                                             RelativeSource="{RelativeSource TemplatedParent}" />
                                    <Binding Path="VerticalOffset"
                                             RelativeSource="{RelativeSource TemplatedParent}" />
                                    <Binding Path="ExtentHeight"
                                             RelativeSource="{RelativeSource TemplatedParent}" />
                                    <Binding Path="ViewportHeight"
                                             RelativeSource="{RelativeSource TemplatedParent}" />
                                </MultiBinding>
                            </RepeatButton.Visibility>
                            <Path Fill="{DynamicResource {x:Static SystemColors.MenuTextBrushKey}}"
                                  Data="{StaticResource UpArrow}" />
                        </RepeatButton>
                        <RepeatButton Focusable="false"
                                      Style="{StaticResource MenuScrollButton}"
                                      Grid.Column="0"
                                      Grid.Row="2"
                                      Command="{x:Static ScrollBar.LineDownCommand}"
                                      CommandTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}">
                            <RepeatButton.Visibility>
                                <MultiBinding FallbackValue="Visibility.Collapsed"
                                              Converter="{StaticResource MenuScrollingVisibilityConverter}"
                                              ConverterParameter="100">
                                    <Binding Path="ComputedVerticalScrollBarVisibility"
                                             RelativeSource="{RelativeSource TemplatedParent}" />
                                    <Binding Path="VerticalOffset"
                                             RelativeSource="{RelativeSource TemplatedParent}" />
                                    <Binding Path="ExtentHeight"
                                             RelativeSource="{RelativeSource TemplatedParent}" />
                                    <Binding Path="ViewportHeight"
                                             RelativeSource="{RelativeSource TemplatedParent}" />
                                </MultiBinding>
                            </RepeatButton.Visibility>
                            <Path Fill="{DynamicResource {x:Static SystemColors.MenuTextBrushKey}}"
                                  Data="{StaticResource DownArrow}" />
                        </RepeatButton>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

And having done that, I ended up with this. Ok I have over styled it for this blog post, but that is easily changed by the 2 RepeatButtons with the key “MenuScrollButton” that the ScrollViewer is using

https://i0.wp.com/dl.dropbox.com/u/2600965/Blogposts/2010/11/ContextMenu/7.png

 

Additional Data That May Be Of Interest

You may actually find these additional links of use, as they do show you how to style Menu/MenuItem controls quite well. I trust these 2 links

Demo App:

As usual here is a small demo app : Demo App

Silverlight, WPF

A Small But Useful Tip

At work at the moment I am working on a large financial LOB app using WPF, where we regularly present the users with various information, some of which they can enter, and some of which they can not.

Now as you can imagine some of this data comes from a database, and as such database ID columns (Primary key values to be precise) are presented to the users. Now these IDs are highly important to our users (who just happen to be internal users within my company), but are obviously read only and database generated, and can grow quite large, as we have a lot of records of certain types of entities.

All following me so far I hope, well now we get to it, in an ideal world everything just works and no one cares about these IDs, and everyone goes about their business. But we are in the process of gradually improving this software (we do Agile iterations of improvements) so things change and occasionally things do go wrong, or do not work as expected, and our users generally relay this to us using the JIRA bug tracking software, where they can place screen shots, if they remember, or catch a problem in time, which quite often is not the case.

So on of those occasions where they do manage to get a screen shot and log it in JIRA that is extremely helpful, but when they do not, guess what is the most important bit of information they can give us.

That’s right we need to know the ID of they thing they were trying to take an action on, and obviously the type of thing they were trying to do at the time the problem occurred. Ok it might be logged, but it could have been an unlogged thing, we have not managed to foresee.

Now as I also mentioned these ID’s can get rather long, and its all too easy to write down the wrong number. I also mentioned that these ID’s are read only, so they are suited to Label type controls. Problem with using Labels is that  the user is unable to copy from them. Sounds a bit rubbish, we could use a ReadOnly TextBox but it just looks a bit naff, looks quite like a normal TextBox, which some users can’t see as being ReadOnly.

So what else can we do, well luckily with WPF we can simply create a TextBox style that makes a ReadOnly TextBox look like a Label, which now allows Copy into an email (say).

Now everyone is happy, we get the right ID sent to our JIRA bug tracking system, or an email, the UI still looks nice, and the TextBox is copy enabled.

Here is a small screenshot showing 3 TextBoxes

  1. A regular TextBox, problem is it allows user to enter Text. So that is out
  2. A ReadOnly TextBox, user can’t enter Text, but it looks like they can
  3. A Styled TextBox which is ReadOnly and looks like a Label and allows Copying from it. This is a winner I think

image

Here is the Style to make a ReadOnly TextBox look like a Label, that still allows copying from.

<Style x:Key="TextBoxStyle1" BasedOn="{x:Null}" TargetType="{x:Type TextBox}">
    <Setter Property="Foreground" Value="Black"/>
    <Setter Property="Background" Value="Transparent"/>
    <Setter Property="BorderBrush" Value="Transparent"/>
    <Setter Property="BorderThickness" Value="1"/>
    <Setter Property="IsReadOnly" Value="true"/>
    <Setter Property="Padding" Value="1"/>
    <Setter Property="AllowDrop" Value="true"/>
    <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
    <Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst"/>
    <Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type TextBox}">
                <Border x:Name="Bd" 
                    BorderThickness="{TemplateBinding BorderThickness}" 
                    SnapsToDevicePixels="true">
                    <ScrollViewer x:Name="PART_ContentHost" 
                    SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

This post is not rocket science, but it may be useful to people that have similar requirements to me I hope.

 

Hope it helps

MVVM, Silverlight, WPF

Cinch + Latest Enhancements = I Am Finally Done

Ok everyone, this is hopefully it my last Cinch posting, then back to some other stuff for me.

I have this weekend made the following enhancements, and they were enhancements there was nothing wrong with codebase prior to this, but they were good ideas people gave me so I included them.

  • Altered Cinch V1 DataWrapper to take a Action in its constructor such that when the Cinch code generator is used the non auto generated part of the overall ViewModel class will be called back using the Action passed to the constructor of the DataWrapper when a property changes. Also got rid of ridiculous condtructors on the DataWrapper class, and also made it a partial class
  • Modified the Cinch code generator to support this, so when you next run the code generator you will see what it did. I basically added another callback call inside of DataWrapper<T> class
  • Altered Cinch V2 DataWrapper the same way as I did for V1 above.
  • Removed small issue in the WorkspaceData.ToString() override where I did not take into account a possible null dataValue. As you never know what this value could be (it could be any object) I have removed the ToString for the dataValue entirely. This is described at : http://cinch.codeplex.com/workitem/4917
  • Made the following classes partial
    • ValidatingObject (Cinch v1 and Cinch v2)
    • ValidatingViewModelBase (Cinch v1 and Cinch v2)
    • ViewModelBase (Cinch v1)
    • ValidatingViewModelBase (Cinch v1)
    • WorkspaceData (Cinch v2 WPF only)
  • Added a new ViewAwareStatusWindow service targeting Windows
  • Added a Non mandatory extra event to WorkSpaceData that can be used to cancel a closing of a workspace. Revised WPF demo to show this for ImageLoader workspace and left About workspace as it was to show it is not mandatory.
  • Resynced with MeffedMVVM release 58837

But that is my done with Cinch now, unless someone finds a bad bug that breaks loads of things in which case I will of course take notice, but until then Hasta La Vista Baby…..More new stuff to enjoy whoohoo

 

Enjoy

MVVM, Silverlight, WPF

Cinch V2 Part 6 : Out Now (Also my 100th article at codeproject)

I have just released the 6th and final part in my Cinch V2 article series. This article covers Silverlight4 support using Cinch.

It can be read using this link :

http://www.codeproject.com/KB/WPF/CinchV2_6.aspx

celebrate

It is also my 100th article over at codeproject, which means a great deal to me, and if you like what I do, I would really appreciate some votes and comments for that article, so please do that, if you feel inclined.

I will be doing a few enhancements to Cinch based on some cool ideas people have suggested. But once I do that, I fully intend on making it to 200 codeproject articles or more. As such I have a massive list of stuff that I want to learn, and I will be cracking on with that, and shall also get back to properly blogging. Enough of this self promotional horse crap thing, that has been happening lately with Cinch, it just had to be done, and it has been done now, so thanks everyone and thanks for all the tuna….But me and Cinch are now done, as I have more interesting things to do.