295 lines
10 KiB
C#
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
|
|
}
|
|
} |