All the controls missing in WPF. Over 1 million downloads.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

258 lines
8.6 KiB

using System;
using System.Linq;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using Microsoft.Windows.Controls.PropertyGrid.Commands;
using System.Windows.Markup.Primitives;
namespace Microsoft.Windows.Controls.PropertyGrid
{
public class PropertyItem : Control
{
#region Members
private DependencyPropertyDescriptor _dpDescriptor;
private MarkupObject _markupObject;
#endregion //Members
#region Properties
#region Category
public static readonly DependencyProperty CategoryProperty = DependencyProperty.Register("Category", typeof(string), typeof(PropertyItem), new UIPropertyMetadata(string.Empty));
public string Category
{
get { return (string)GetValue(CategoryProperty); }
set { SetValue(CategoryProperty, value); }
}
#endregion //Category
public string Description { get { return PropertyDescriptor.Description; } }
#region Editor
public static readonly DependencyProperty EditorProperty = DependencyProperty.Register("Editor", typeof(FrameworkElement), typeof(PropertyItem), new UIPropertyMetadata(null));
public FrameworkElement Editor
{
get { return (FrameworkElement)GetValue(EditorProperty); }
set { SetValue(EditorProperty, value); }
}
#endregion //Editor
private object _instance;
public object Instance
{
get
{
return _instance;
}
private set
{
_instance = value;
_markupObject = MarkupWriter.GetMarkupObjectFor(_instance);
}
}
/// <summary>
/// Gets if the property is data bound
/// </summary>
public bool IsDataBound
{
get
{
var dependencyObject = Instance as DependencyObject;
if (dependencyObject != null && _dpDescriptor != null)
return BindingOperations.GetBindingExpressionBase(dependencyObject, _dpDescriptor.DependencyProperty) != null;
return false;
}
}
public bool IsDynamicResource
{
get
{
var markupProperty = _markupObject.Properties.Where(p => p.Name == PropertyDescriptor.Name).FirstOrDefault();
if (markupProperty != null)
return markupProperty.Value is DynamicResourceExtension;
return false;
}
}
public bool HasResourceApplied
{
//TODO: need to find a better way to determine if a StaticResource has been applied to any property not just a style
get
{
var markupProperty = _markupObject.Properties.Where(p => p.Name == PropertyDescriptor.Name).FirstOrDefault();
if (markupProperty != null)
return markupProperty.Value is Style;
return false;
}
}
public bool IsReadOnly { get { return PropertyDescriptor.IsReadOnly; } }
#region IsSelected
public static readonly DependencyProperty IsSelectedProperty = DependencyProperty.Register("IsSelected", typeof(bool), typeof(PropertyItem), new UIPropertyMetadata(false, OnIsSelectedChanged));
public bool IsSelected
{
get { return (bool)GetValue(IsSelectedProperty); }
set { SetValue(IsSelectedProperty, value); }
}
private static void OnIsSelectedChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
PropertyItem propertyItem = o as PropertyItem;
if (propertyItem != null)
propertyItem.OnIsSelectedChanged((bool)e.OldValue, (bool)e.NewValue);
}
protected virtual void OnIsSelectedChanged(bool oldValue, bool newValue)
{
if (newValue)
PropertyGrid.SelectedProperty = this;
}
#endregion //IsSelected
public bool IsWriteable { get { return !IsReadOnly; } }
private PropertyDescriptor _propertyDescriptor;
public PropertyDescriptor PropertyDescriptor
{
get
{
return _propertyDescriptor;
}
private set
{
_propertyDescriptor = value;
Name = _propertyDescriptor.Name;
Category = _propertyDescriptor.Category;
_dpDescriptor = DependencyPropertyDescriptor.FromProperty(_propertyDescriptor);
}
}
public PropertyGrid PropertyGrid { get; private set; }
public Type PropertyType { get { return PropertyDescriptor.PropertyType; } }
public ICommand ResetValueCommand { get; private set; }
#region Value
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(object), typeof(PropertyItem), new UIPropertyMetadata(null, OnValueChanged));
public object Value
{
get { return (object)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
private static void OnValueChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
PropertyItem propertyItem = o as PropertyItem;
if (propertyItem != null)
propertyItem.OnValueChanged((object)e.OldValue, (object)e.NewValue);
}
protected virtual void OnValueChanged(object oldValue, object newValue)
{
// TODO: Add your property changed side-effects. Descendants can override as well.
}
#endregion //Value
/// <summary>
/// Gets the value source.
/// </summary>
public BaseValueSource ValueSource
{
get
{
var dependencyObject = Instance as DependencyObject;
if (_dpDescriptor != null && dependencyObject != null)
return DependencyPropertyHelper.GetValueSource(dependencyObject, _dpDescriptor.DependencyProperty).BaseValueSource;
return BaseValueSource.Unknown;
}
}
#endregion //Properties
#region Constructor
static PropertyItem()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(PropertyItem), new FrameworkPropertyMetadata(typeof(PropertyItem)));
}
public PropertyItem(object instance, PropertyDescriptor property, PropertyGrid propertyGrid)
{
PropertyDescriptor = property;
PropertyGrid = propertyGrid;
Instance = instance;
CommandBindings.Add(new CommandBinding(PropertyItemCommands.ResetValue, ExecuteResetValueCommand, CanExecuteResetValueCommand));
AddHandler(Mouse.MouseDownEvent, new MouseButtonEventHandler(PropertyItem_MouseDown), true);
AddHandler(Mouse.PreviewMouseDownEvent, new MouseButtonEventHandler(PropertyItem_PreviewMouseDown), true);
}
#endregion //Constructor
#region Event Handlers
void PropertyItem_MouseDown(object sender, MouseButtonEventArgs e)
{
if (Editor != null)
Editor.Focus();
e.Handled = true;
}
void PropertyItem_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
IsSelected = true;
//if it is a comboBox then the selection will not take when Focus is called
if (!(e.Source is ComboBox))
Focus();
}
#endregion //Event Handlers
#region Commands
private void ExecuteResetValueCommand(object sender, ExecutedRoutedEventArgs e)
{
if (PropertyDescriptor.CanResetValue(Instance))
PropertyDescriptor.ResetValue(Instance);
//TODO: notify UI that the ValueSource may have changed to update the icon
}
private void CanExecuteResetValueCommand(object sender, CanExecuteRoutedEventArgs e)
{
bool canExecute = false;
if (PropertyDescriptor.CanResetValue(Instance) && !PropertyDescriptor.IsReadOnly)
{
canExecute = true;
}
e.CanExecute = canExecute;
}
#endregion //Commands
}
}