Sic.Framework/MECF.Framework.UI.Client/DataGridTransform/DataGrid/Microsoft/Windows/Controls/DataGridHyperlinkColumn.cs

295 lines
10 KiB
C#

//---------------------------------------------------------------------------
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//
//---------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using EGC = ExtendedGrid.Microsoft.Windows.Controls;
namespace ExtendedGrid.Microsoft.Windows.Controls
{
/// <summary>
/// A column that displays a hyperlink.
/// </summary>
public class DataGridHyperlinkColumn : EGC.DataGridBoundColumn
{
static DataGridHyperlinkColumn()
{
ElementStyleProperty.OverrideMetadata(typeof(EGC.DataGridHyperlinkColumn), new FrameworkPropertyMetadata(DefaultElementStyle));
EditingElementStyleProperty.OverrideMetadata(typeof(EGC.DataGridHyperlinkColumn), new FrameworkPropertyMetadata(DefaultEditingElementStyle));
}
#region Hyperlink Column Properties
/// <summary>
/// Dependecy property for TargetName Property
/// </summary>
public static readonly DependencyProperty TargetNameProperty =
Hyperlink.TargetNameProperty.AddOwner(
typeof(EGC.DataGridHyperlinkColumn),
new FrameworkPropertyMetadata(null, new PropertyChangedCallback(EGC.DataGridColumn.NotifyPropertyChangeForRefreshContent)));
/// <summary>
/// The property which determines the target name of the hyperlink
/// </summary>
public string TargetName
{
get { return (string)GetValue(TargetNameProperty); }
set { SetValue(TargetNameProperty, value); }
}
/// <summary>
/// The binding to the content to be display under hyperlink
/// </summary>
public BindingBase ContentBinding
{
get
{
return _contentBinding;
}
set
{
if (_contentBinding != value)
{
BindingBase oldValue = _contentBinding;
_contentBinding = value;
OnContentBindingChanged(oldValue, value);
}
}
}
/// <summary>
/// Called when ContentBinding changes.
/// </summary>
/// <remarks>
/// Default implementation notifies the DataGrid and its subtree about the change.
/// </remarks>
/// <param name="oldBinding">The old binding.</param>
/// <param name="newBinding">The new binding.</param>
protected virtual void OnContentBindingChanged(BindingBase oldBinding, BindingBase newBinding)
{
NotifyPropertyChanged("ContentBinding");
}
/// <summary>
/// Try applying ContentBinding. If it doesnt work out apply Binding.
/// </summary>
/// <param name="target"></param>
/// <param name="property"></param>
private void ApplyContentBinding(DependencyObject target, DependencyProperty property)
{
if (ContentBinding != null)
{
BindingOperations.SetBinding(target, property, ContentBinding);
}
else if (Binding != null)
{
BindingOperations.SetBinding(target, property, Binding);
}
else
{
BindingOperations.ClearBinding(target, property);
}
}
#endregion
#region Property Changed Handler
/// <summary>
/// Override which rebuilds the cell's visual tree for ContentBinding change
/// and Modifies Hyperlink for TargetName change
/// </summary>
/// <param name="element"></param>
/// <param name="propertyName"></param>
protected internal override void RefreshCellContent(FrameworkElement element, string propertyName)
{
EGC.DataGridCell cell = element as EGC.DataGridCell;
if (cell != null && !cell.IsEditing)
{
if (string.Compare(propertyName, "ContentBinding", StringComparison.Ordinal) == 0)
{
cell.BuildVisualTree();
}
else if (string.Compare(propertyName, "TargetName", StringComparison.Ordinal) == 0)
{
TextBlock outerBlock = cell.Content as TextBlock;
if (outerBlock != null && outerBlock.Inlines.Count > 0)
{
Hyperlink link = outerBlock.Inlines.FirstInline as Hyperlink;
if (link != null)
{
link.TargetName = TargetName;
}
}
}
}
else
{
base.RefreshCellContent(element, propertyName);
}
}
#endregion
#region Styles
/// <summary>
/// The default value of the ElementStyle property.
/// This value can be used as the BasedOn for new styles.
/// </summary>
public static Style DefaultElementStyle
{
get { return EGC.DataGridTextColumn.DefaultElementStyle; }
}
/// <summary>
/// The default value of the EditingElementStyle property.
/// This value can be used as the BasedOn for new styles.
/// </summary>
public static Style DefaultEditingElementStyle
{
get { return EGC.DataGridTextColumn.DefaultEditingElementStyle; }
}
#endregion
#region Element Generation
/// <summary>
/// Creates the visual tree for cells.
/// </summary>
protected override FrameworkElement GenerateElement(EGC.DataGridCell cell, object dataItem)
{
TextBlock outerBlock = new TextBlock();
Hyperlink link = new Hyperlink();
InlineUIContainer inlineContainer = new InlineUIContainer();
ContentPresenter innerContentPresenter = new ContentPresenter();
outerBlock.Inlines.Add(link);
link.Inlines.Add(inlineContainer);
inlineContainer.Child = innerContentPresenter;
link.TargetName = TargetName;
ApplyStyle(/* isEditing = */ false, /* defaultToElementStyle = */ false, outerBlock);
ApplyBinding(link, Hyperlink.NavigateUriProperty);
ApplyContentBinding(innerContentPresenter, ContentPresenter.ContentProperty);
return outerBlock;
}
/// <summary>
/// Creates the visual tree for cells.
/// </summary>
protected override FrameworkElement GenerateEditingElement(EGC.DataGridCell cell, object dataItem)
{
TextBox textBox = new TextBox();
ApplyStyle(/* isEditing = */ true, /* defaultToElementStyle = */ false, textBox);
ApplyBinding(textBox, TextBox.TextProperty);
return textBox;
}
#endregion
#region Editing
/// <summary>
/// Called when a cell has just switched to edit mode.
/// </summary>
/// <param name="editingElement">A reference to element returned by GenerateEditingElement.</param>
/// <param name="editingEventArgs">The event args of the input event that caused the cell to go into edit mode. May be null.</param>
/// <returns>The unedited value of the cell.</returns>
protected override object PrepareCellForEdit(FrameworkElement editingElement, RoutedEventArgs editingEventArgs)
{
TextBox textBox = editingElement as TextBox;
if (textBox != null)
{
textBox.Focus();
string originalValue = textBox.Text;
TextCompositionEventArgs textArgs = editingEventArgs as TextCompositionEventArgs;
if (textArgs != null)
{
// If text input started the edit, then replace the text with what was typed.
string inputText = textArgs.Text;
textBox.Text = inputText;
// Place the caret after the end of the text.
textBox.Select(inputText.Length, 0);
}
else
{
// If something else started the edit, then select the text
textBox.SelectAll();
}
return originalValue;
}
return null;
}
/// <summary>
/// Called when a cell's value is to be committed, just before it exits edit mode.
/// </summary>
/// <param name="editingElement">A reference to element returned by GenerateEditingElement.</param>
/// <returns>false if there is a validation error. true otherwise.</returns>
protected override bool CommitCellEdit(FrameworkElement editingElement)
{
TextBox textBox = editingElement as TextBox;
if (textBox != null)
{
EGC.DataGridHelper.UpdateSource(textBox, TextBox.TextProperty);
return !Validation.GetHasError(textBox);
}
return true;
}
/// <summary>
/// Called when a cell's value is to be cancelled, just before it exits edit mode.
/// </summary>
/// <param name="editingElement">A reference to element returned by GenerateEditingElement.</param>
/// <returns>false if there is a validation error. true otherwise.</returns>
protected override void CancelCellEdit(FrameworkElement editingElement, object uneditedValue)
{
TextBox textBox = editingElement as TextBox;
if (textBox != null)
{
EGC.DataGridHelper.UpdateTarget(textBox, TextBox.TextProperty);
}
}
internal override void OnInput(InputEventArgs e)
{
// Text input will start an edit
if (e is TextCompositionEventArgs)
{
BeginEdit(e);
}
}
#endregion
#region Data
private BindingBase _contentBinding = null;
#endregion
}
}