Archive

Posts Tagged ‘Behaviors’

Using Behaviors and Triggers in Xaml

April 23, 2011 Leave a comment

I had a great time presenting to the WNC .NET Developers Guild last night. Here is a link to the slides and source code.

Hope you enjoy and thank you to those who came out!

Advertisements

Using Behaviors and Triggers in Xaml

April 13, 2011 Leave a comment

I will be doing a presentation on Thursday, April 21 at the WNC .NET Developers Guild. Here is a summary of the presentation:

We will review what Behaviors and Triggers are all about. We will then discover how we can use them and see how they can enable us as developers. We will also discuss how Behaviors and Triggers allow us to develop following the Model-View-ViewModel (MVVM) pattern. Finally, we will dive into code and examine some common behaviors and triggers that we can use in our line of business applications.

Looking forward to it!

Automatically scrolling to a selected item in a ScrollViewer in Silverlight

January 15, 2011 Leave a comment

Sometimes it is necessary to have some custom user interactions as you are building business applications. It became necessary during a design session that the client needed the ability to design their own bill layouts. They needed the ability to basically drag and drop controls on the screen to build an invoice to send to their customers. With the power of Silverlight, I wanted to present them with a grid or canvas and allow them to create their own layouts. The problem with this is that they started making really complex layouts that made perfect sense to them but required scrolling during the design phase of the bill. One issue that came up is that when they wanted to navigate to an input control, they had to scroll and search for the control. I am using a ValidationSummary control to provide validation errors but since I was out of the context of a DataForm, I couldn’t just have my custom controls get highlighted. So I found two different implementations that provided a good starting ground but I wanted to have both vertical and horizontal navigation. I created a Behavior to support this and now when a user clicks on an item in the ValidationSummary control, they are navigated to the corresponding control.

The following is a sample screen shot of one of the bill design that was created:

Bill Designer

The following is a screen shot when the user click on the item in error:

Bill Designer - Auto Scroll

Here is the implementation for the Behavior:

 public class ScrollToSelectedItemBahavior : Behavior<ScrollViewer>
{
	private const int SCROLL_PADDING = 10;

	#region Overrides
	protected override void OnAttached()
	{
		base.OnAttached();

		this.AssociatedObject.Loaded += OnLoaded;
	}

	protected override void OnDetaching()
	{
		base.OnDetaching();

		this.AssociatedObject.Loaded -= OnLoaded;
		var controls = this.AssociatedObject.GetVisualDescendants();
		foreach (FrameworkElement control in controls)
		{
			control.GotFocus -= Control_GotFocus;
		}
	}
	#endregion

	#region Events

	private void OnLoaded(object sender, RoutedEventArgs e)
	{
		var controls = AssociatedObject.GetVisualDescendants();
		foreach (FrameworkElement control in controls)
		{
			control.GotFocus += Control_GotFocus;
		}
	}

	private void Control_GotFocus(object sender, RoutedEventArgs e)
	{
		FrameworkElement element = e.OriginalSource as FrameworkElement;
		var transform = element.TransformToVisual(AssociatedObject);
		var positionInScrollViewer = transform.Transform(new Point(0, 0));

		if (positionInScrollViewer.Y < 0 || 
			positionInScrollViewer.Y > AssociatedObject.ViewportHeight)
		{
			AssociatedObject.ScrollToVerticalOffset(AssociatedObject.VerticalOffset + 
				positionInScrollViewer.Y - SCROLL_PADDING);
		}

		if (positionInScrollViewer.X < 0 || 
			positionInScrollViewer.X > AssociatedObject.ViewportWidth)
		{
			AssociatedObject.ScrollToHorizontalOffset(AssociatedObject.HorizontalOffset + 
				positionInScrollViewer.X - SCROLL_PADDING);
		}
	}

	#endregion

};

As with any Behavior you need to add a using statement for System.Windows.Interactivity. In this example, I am also using some helper functions from the Silverlight Toolkit and I also have a using statement for System.Windows.Controls.Primitives.

Basically, when we attach the Behavior to the underlying control, we wire up the Loaded event and in this event we cycle through all the descendants and wire up the GotFocus event. It is the method call GetVisualDescendants that is the helper method from the Silverlight Toolkit. Conversely, when we are detaching we unwire all of the GotFocus events.

In the Control_GotFocus method we simply create a transform and then scroll vertically, horizontally, or both depending on where the control is located.

That is basically all there is to coding this Behavior.

Now, let’s look at the Xaml required to get this to work:

<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
	<i:Interaction.Behaviors>
		<core:ScrollToSelectedItemBahavior/>
	</i:Interaction.Behaviors>
	<Grid 
		x:Name="grdDesigner"
		Margin="10,10,10,10" 
		ShowGridLines="True"
		radDrag:RadDragAndDropManager.AllowDrop="True" 
		Background="#FF2D2D2D">
		<i:Interaction.Triggers>
			<i:EventTrigger EventName="MouseLeftButtonDown">
				<core:ExecuteDataMethod Method="Designer_MouseLeftButtonDown" />
			</i:EventTrigger>
		</i:Interaction.Triggers>

	</Grid>
</ScrollViewer>

The following are the links that got me started and show a slightly different implementation:
Silverlight 4 ScrollViewer & Keeping items in view
Silverlight BringIntoView() extension method (with OnGotFocus behavior)

Hope this helps…

Categories: English Tags: , ,

Behaviors and Triggers in Silverlight

August 6, 2010 2 comments

I will be doing a presentation this coming Tuesday, August 10 at the WNC .NET Developers Guild. Here is a summary of the presentation:

Since Silverlight 3 we have had the opportunity to work with Behaviors and Triggers. Most of our exposure has been limited to Blend since the bits come from the Blend application. In this presentation, we will analyze both Behaviors and Triggers and then look at what it takes to build a behavior and trigger from scratch. We will also discuss how we can use Behaviors and Triggers to support Model-View-ViewModel (MVVM) as well. Finally, we will look at where we can use Behaviors and Triggers in our applications in a practical approach. Instead of just showing simple animations, we will look at how we can use these powerful features to get component and logic re-use as much as possible.

Looking forward to it!

Behaviors and all that fun stuff…

The other day I was catching up on some of Dan Wahlin’s posts and I read his post about providing a DataContext to controls that needed to access the ViewModel but were in a sub-collection.  He went through some good approaches as to how one could go about solving this problem.

I would like to also offer up another approach that is quite similar to his but with a twist.  I agree that, if possible, it keeps things simple if you can provide a way to reach out to the underlying ViewModel no matter what the nesting level your control resides in.  In my experience, I rarely find a solution that works best for all of my scenarios but I have found several solutions that tend to handle most of the the issues I come across.

Before we go further, I would like to present the general approach that I use to build these solutions.  I use Behaviors.  These guys live in the System.Windows.Interactivity namespace.  They provide a very powerful way to write code once and use over and over in your Xaml.

I will present them first in a list and then provide a detailed explanation when each would be used:

  • DataContextToDomainDataSourceBehavior — this behavior exposes a property, “ControlName”.  It uses this to walk up the Visual Tree until it finds such a control and then sets the DataContext of the underlying control for which this behavior is set.  The DataContext gets set on the Loaded event.
  • ItemSourceBehavior — This behavior has a lot of flexibility.  It exposes “ItemsSourceName”, “IsEnum”, “EnumFilter” properties.  This behavior works on any ItemsControl, DataGrid, and Telerik RadGridView.  If the IsEnum flag is set, then it is smart enough to set the ItemsSource to the named enum.  Otherwise, it will find the named property on the DataContext.  This behavior explicitly looks for the first UserControl it can find and grabs its DataContext.
  • ItemSourceBindingBehavior — This is basically the same as the previous behavior but this one binds the ItemsSource to the underlying property.  This facilitates for a more MVVM style of programming.
  • ItemSourceToDomainDataSourceBehavior — This fires on the loaded event and has a property that holds the name of a DomainDataSource.  This behviour explicitly looks for the first UserControl it can find and then looks for a DomainDataSource with the given name.  If it finds it then ItemSource property is bound to the DomainDataSource.  This happens for ItemsControls and the DataGrid.

Each of these behaviors performs a specific task and has certain capabilities.  As you can see, there may be scenarios that you could use that are not exposed by what I have show here.  I will go further into how these work in a later post.


Categories: English Tags: ,