Apr
24
2010
WPF // MVVM // Telerik

Telerik Binding RadPaneGroup to an ObservableCollection in WPF MVVM

I had this done in AvalonDock (read my post here) but we purchased the Telerik Controls so I decided to convert my AvalonDock solution to Telerick RadDocking control. By the way Telerik does an awesome job with their controls and excellent customer service. My requirement was to have a dynamicaly populated tab document collection in the DocumentHost. Using the MVVM pattern I have a ViewModel bound to a Window which contains the RadDocking control. Binding a RadPaneGroup to an observable collection work fine populating the tabs but they cannot be closed using the built-in controls. So I placed a button on the tab header to remove the item from the ObservableCollection. I added a cutom header template to the window resources. It uses a custom style ImageButtonStyle to give it a compact look and it calls the command CloseTabCommand on the ViewModel which after running some checks removes the SelectedRadPane from the RadPaneList collection. So the ViewModel has the following properties bound to the xaml public ObservableCollection<RadDocumentPane> RadPaneList { get; private set; } public RadDocumentPane SelectedRadPane { get; set;} And in order to add a RadDocumentPane to the collection I do the following which presumes there is a property Title on the ViewModel to bind the header to. It creates a new instance of the control to be displayed in the new tab and binds it to an instance of the respective ViewModel System.Windows.Data.Binding binding = new System.Windows.Data.Binding("Title"); RadDocumentPane documentPane = new RadDocumentPane(); documentPane.SetBinding(RadDocumentPane.HeaderProperty, binding); documentPane.SetBinding(RadDocumentPane.ToolTipProperty, binding); documentPane.SetResourceReference(RadDocumentPane.HeaderTemplateProperty, "HeaderTemplate"); documentPane.CanUserClose = false; documentPane.CanFloat = false; documentPane.ContextMenuTemplate = null; MyCustomContro myControl = new MyCustomControl(); documentPane.DataContext = new DocumentPaneViewModel(); documentPane.Content = myControl; RadPaneList.Add(documentPane); Enjoy
Nov
4
2009
WPF // MVVM

WPF Cursor Handling Routine

In my WPF application I need to change the cursor to identify a potentially long running process. The cursor needs to change back when the process completes regardless if it throws back an exception or not. So I ended up writing the class below to do just that. public class CursorRoutine : IDisposable { private System.Windows.Input.Cursor _oldCursor; public CursorRoutine() : this(null) { } public CursorRoutine(System.Windows.Input.Cursor oldCursor) : this(oldCursor, System.Windows.Input.Cursors.Wait) { } public CursorRoutine( System.Windows.Input.Cursor oldCursor, System.Windows.Input.Cursor newCursor) { _oldCursor = oldCursor; System.Windows.Input.Mouse.OverrideCursor = newCursor; } #region IDisposable Members private bool isDisposed; /// /// Finilize method /// ~CursorRoutine() { Dispose(false); } /// /// Releases all resources used by the object /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// /// Releases all resources used by the object /// /// Disposing Flag protected virtual void Dispose(bool disposing) { if (!isDisposed) { if (disposing) { //Dispose of managed resources System.Windows.Input.Mouse.OverrideCursor = _oldCursor; } //Dispose of unmanaged resources } isDisposed = true; } #endregion } The it can be used like that: using (CursorRoutine cursor = new CursorRoutine()) { //...... A call to a long running process }
Jul
30
2009

AvalonDock Binding DocumentContent in WPF MVVM

I'm working on a WPF application using the MVVM pattern. I'm using the AvalonDock to achieve a Visual Studio look and feel. We needed to have a Tab collection, very much like the open documents in Visual Studio that have to be added and removed at design time. In order to accomplish this we created an ObservableCollection of DocumentContent and bound the DocumentPane ItemsSource to it. So we have a collection of DocumentContent, and a property for the Selected Item. The code also assumes that you have an Images folder directly under the project in order to add an icon to the dropdown selector at the right end. [CLSCompliant(false)] public ObservableCollection<AvalonDock.DocumentContent> DocumentContents { get; private set; } public AvalonDock.DocumentContent SelectedTab { get; set; } The code below goes in the ViewModel of the Window or controls that has the AvalonDock control. public interface ITabViewModel { Guid ObjectId { get; } } public void AddTabViewModel(ITabViewModel tabViewModel) { //if the viewmodel is already added to the tabs just select it. AvalonDock.DocumentContent existingControl = DocumentContents.SingleOrDefault(x => (Guid)x.Tag == tabViewModel.ObjectId); if (existingControl != null) { existingControl.Focus(); exists = true; return; } System.Windows.Data.Binding binding = new System.Windows.Data.Binding("Title"); AvalonDock.DocumentContent avalonDoc = new AvalonDock.DocumentContent() { Title = binding.ToString() }; avalonDoc.SetBinding(AvalonDock.DocumentContent.TitleProperty, binding); avalonDoc.Tag = tabViewModel.ObjectId; System.Windows.Controls.Image iconImage = new System.Windows.Controls.Image() { Width = 16, Height = 16 }; BitmapImage image = new BitmapImage(new Uri(@"pack://application:,,,/Images/cubes.png")); iconImage.Source = image; avalonDoc.Icon = iconImage; MyUserControl myControl = new MyUserControl(); avalonDoc.DataContext = tabViewModel; avalonDoc.Content = myControl; DocumentContents.Insert(0, avalonDoc); avalonDoc.Focus(); }   And this is the XAML bound to the collection of DocumentContents added to the AvalonDock DockingManager or ResizingPanel. <ad:ResizingPanel Orientation="Vertical"> <ad:DocumentPane ItemsSource="{Binding Path=DocumentContents}" SelectedItem="{Binding SelectedTab}" Background="White" > </ad:DocumentPane> </ad:ResizingPanel>