views:

1780

answers:

4

I'm trying to get some WPF concepts down, so I've put together a simple example of what I'm trying to do. I would like to set a custom property of a user control, and have it be used by an element within the control.

I've been researching and experimenting, but I'm not fully understanding everything here. Any help would be appreciated.

The user control for this example is a simple square with a circle inside of it:

<UserControl x:Class="CircleInSquare"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="100" Height="100" >
    <Grid Background="#000000">
        <Ellipse Name="Circle"
                 Margin="10"
                 Fill="?????????"
                 >
        </Ellipse>
    </Grid>
</UserControl>

The VB Code Behind it:

Partial Public Class CircleInSquare

    Private _CircleColor As Color

    Public Property CircleColor() As Color
        Get
            Return _CircleColor
        End Get
        Set(ByVal value As Color)
            _CircleColor = value
        End Set
    End Property

End Class

When I use this user control, how can I apply a CircleColor to the control, and have it be shown as the Ellipse's fill color? Even better... can I give it a default color that shows up in the VS2008 Designer?

So... if I place one of these into my window XAML like this:

<app:CircleInSquare CircleColor="Blue" />

I would like the circle to display as Blue (or any other color I choose for that instance)

A: 

You need to create a DependencyProperty in your CircleInSquare class. Do some googling on that. The concept of using the property for your circle class like below is called AttachedProperties, and you will probably need to handle the CircleColorChanged event to do what you need.

<Ellipse app:CircleInSquare.CircleColor="Blue" />
bendewey
I tried doing some work with Dependency Properties, but so many of the examples I found were so complicated or unclear, or written in C#. I haven't found a good simple example as of yet, but I will continue to experiment. I wasn't sure if that was the right way to go since it wasn't working for me.
B2Ben
A dependency property is really what you need. Maybe there are other ways to do it, but doing it with a dependency property is in harmony with the overall philosophy of WPF. I'd provide an example, but I suck big time at VB and you don't want C#...
Boyan
are your familiar with CodeSnippets. There is a code snippet in VB for depency properties (wpfdp, wpfdpa, wpfdpo)
bendewey
A: 

Set the DataContext for the ellipse to an instance of your CircleInSquare class. And make sure you use implement INotifyProperychanged on this class to make it property change enabled. check this link if you need more info on Propertychange

  <Ellipse Name="Circle"
             Margin="10"
             Fill="{Binding Path= CircleColor}"
             >
    </Ellipse>
Jobi Joy
A: 

You set up a dependency property like this:

Public Shared ReadOnly MouseOverBrushProperty As DependencyProperty = DependencyProperty.Register("MouseOverBrush", GetType(Brush), GetType(BrushableComboBox), New UIPropertyMetadata())
Public Property MouseOverBrush() As Brush
    Get
     Return CType(GetValue(MouseOverBrushProperty), Brush)
    End Get
    Set(ByVal value As Brush)
     SetValue(MouseOverBrushProperty, value)
    End Set
End Property

And then in your xaml you do something like this

Background="{TemplateBinding MouseOverBrush}"

and you can set a default style outside of the control template like this:

<Style TargetType="{x:Type local:BrushableComboBox}">
    <Setter Property="MouseOverBrush" Value="Blue" />
    ...

You might also be able to do it with a normal property but dependency properties support binding which makes styling much easier later.

HTH

Bryan Anderson
+1  A: 

Sorry to repost, but After re-reading you post, I think that you might be better off with templating. I've attached some samples in VB

Window.xaml

<Window x:Class="Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:app="clr-namespace:WpfApplicationVB1"
    Title="Window1" Height="300" Width="300">
    <Grid>
        <app:CircleInSquare Height="50" Width="50" CircleColor="Blue" SquareColor="Red"  />
    </Grid>
</Window>

CircleInSquare.xaml.vb

Partial Public Class CircleInSquare
    Public Property CircleColor() As Brush
        Get
            Return GetValue(CircleColorProperty)
        End Get

        Set(ByVal value As Brush)
            SetValue(CircleColorProperty, value)
        End Set
    End Property

    Public Shared ReadOnly CircleColorProperty As DependencyProperty = _
                           DependencyProperty.Register("CircleColor", _
                           GetType(Brush), GetType(CircleInSquare), _
                           New FrameworkPropertyMetadata(Brushes.Black))


    Public Property SquareColor() As Brush
        Get
            Return GetValue(SquareColorProperty)
        End Get

        Set(ByVal value As Brush)
            SetValue(SquareColorProperty, value)
        End Set
    End Property

    Public Shared ReadOnly SquareColorProperty As DependencyProperty = _
                           DependencyProperty.Register("SquareColor", _
                           GetType(Brush), GetType(CircleInSquare), _
                           New FrameworkPropertyMetadata(Brushes.Gray))

End Class

CircleInSquare.xaml

<UserControl x:Class="CircleInSquare"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:app="clr-namespace:WpfApplicationVB1"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"&gt;
    <UserControl.Template>
        <ControlTemplate>
        <Border x:Name="PART_Square" Height="{TemplateBinding Height}"  Width="{TemplateBinding Width}" Background="{TemplateBinding app:CircleInSquare.SquareColor}">
        <Ellipse x:Name="PART_Ellipse" Height="{TemplateBinding Height}"
                 Width="{TemplateBinding Width}" Fill="{TemplateBinding app:CircleInSquare.CircleColor}" />
            </Border>
        </ControlTemplate>
    </UserControl.Template>
</UserControl>
bendewey
Fantastic bendewey! I'll take the concepts and apply it to my custom control. I know this works, but haven't yet understood why, or why temnplating is the best choice. If you or anyone else can explain the virtues of templating in this type of situation, it would be appreciated :-)
B2Ben
To me it really boils down to how your going to use the control. In your case you need to have flexibility over the contents of the control and you want to expose the contents of the control to the users of the control. Templating allows users to style your contents after the fact.
bendewey
I would use Binding for data when you want to keep the data/contents of one property synced with another property. The other option of attached properties is really best when you want to extend the behavior of your control to a control outside of your control.
bendewey