mirror of
https://gitee.com/akwkevin/aistudio.-wpf.-diagram
synced 2026-04-08 18:26:35 +08:00
项目结构调整
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using Windows.Foundation.Collections;
|
||||
using Windows.UI.Xaml;
|
||||
|
||||
namespace LiveCharts.Uwp.Components.MultiBinding
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a collection of <see cref="DependencyObject"/> instances of a specified type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of items in the collection.</typeparam>
|
||||
public class DependencyObjectCollection<T> : DependencyObjectCollection, INotifyCollectionChanged
|
||||
where T : DependencyObject
|
||||
{
|
||||
/// <summary>
|
||||
/// Occurs when items in the collection are added, removed, or replaced.
|
||||
/// </summary>
|
||||
public event NotifyCollectionChangedEventHandler CollectionChanged;
|
||||
|
||||
private readonly List<T> _oldItems = new List<T>();
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DependencyObjectCollection{T}" /> class.
|
||||
/// </summary>
|
||||
public DependencyObjectCollection()
|
||||
{
|
||||
VectorChanged += DependencyObjectCollectionVectorChanged;
|
||||
}
|
||||
|
||||
private void DependencyObjectCollectionVectorChanged(IObservableVector<DependencyObject> sender, IVectorChangedEventArgs e)
|
||||
{
|
||||
var index = (int)e.Index;
|
||||
|
||||
switch (e.CollectionChange)
|
||||
{
|
||||
case CollectionChange.Reset:
|
||||
foreach (var item in this)
|
||||
{
|
||||
VerifyType(item);
|
||||
}
|
||||
|
||||
RaiseCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
|
||||
|
||||
_oldItems.Clear();
|
||||
|
||||
break;
|
||||
|
||||
case CollectionChange.ItemInserted:
|
||||
VerifyType(this[index]);
|
||||
|
||||
RaiseCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, this[index], index));
|
||||
|
||||
_oldItems.Insert(index, (T)this[index]);
|
||||
|
||||
break;
|
||||
|
||||
case CollectionChange.ItemRemoved:
|
||||
RaiseCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, _oldItems[index], index));
|
||||
|
||||
_oldItems.RemoveAt(index);
|
||||
|
||||
break;
|
||||
|
||||
case CollectionChange.ItemChanged:
|
||||
VerifyType(this[index]);
|
||||
|
||||
RaiseCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, this[index], _oldItems[index]));
|
||||
|
||||
_oldItems[index] = (T)this[index];
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the <see cref="CollectionChanged"/> event with the provided event data.
|
||||
/// </summary>
|
||||
/// <param name="eventArgs">The event data.</param>
|
||||
protected void RaiseCollectionChanged(NotifyCollectionChangedEventArgs eventArgs)
|
||||
{
|
||||
var eventHandler = CollectionChanged;
|
||||
|
||||
if (eventHandler != null)
|
||||
{
|
||||
eventHandler(this, eventArgs);
|
||||
}
|
||||
}
|
||||
|
||||
private void VerifyType(DependencyObject item)
|
||||
{
|
||||
if (!(item is T))
|
||||
{
|
||||
throw new InvalidOperationException("Invalid item type added to collection");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Data;
|
||||
using Windows.UI.Xaml.Markup;
|
||||
using Microsoft.Xaml.Interactivity;
|
||||
|
||||
namespace LiveCharts.Uwp.Components.MultiBinding
|
||||
{
|
||||
/// <summary>
|
||||
/// The behavior that enables multiple binding.
|
||||
/// </summary>
|
||||
[ContentProperty(Name = "Items")]
|
||||
[TypeConstraint(typeof(FrameworkElement))]
|
||||
public class MultiBindingBehavior : Behavior<FrameworkElement>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the <see cref="MultiBindingItem"/> collection within this <see cref="MultiBindingBehavior"/> instance.
|
||||
/// </summary>
|
||||
/// <value>One or more <see cref="MultiBindingItem"/> objects.</value>
|
||||
public MultiBindingItemCollection Items
|
||||
{
|
||||
get { return (MultiBindingItemCollection)GetValue(ItemsProperty); }
|
||||
private set { SetValue(ItemsProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Identifier for the <see cref="Items" /> dependency property.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty ItemsProperty =
|
||||
DependencyProperty.Register(nameof(Items), typeof(MultiBindingItemCollection), typeof(MultiBindingBehavior), null);
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the path to the binding source property.
|
||||
/// </summary>
|
||||
/// <value>The path to the binding source property.</value>
|
||||
public string PropertyName
|
||||
{
|
||||
get { return (string)GetValue(PropertyNameProperty); }
|
||||
set { SetValue(PropertyNameProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Identifier for the <see cref="PropertyName" /> dependency property.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty PropertyNameProperty =
|
||||
DependencyProperty.Register(nameof(PropertyName), typeof(string), typeof(MultiBindingBehavior), new PropertyMetadata(null, OnPropertyChanged));
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the converter to use to convert the source values to or from the target value.
|
||||
/// </summary>
|
||||
/// <value>A resource reference to a class that implements the <see cref="IValueConverter"/> interface, which includes implementations of the <see cref="IValueConverter.Convert"/> and <see cref="IValueConverter.ConvertBack"/> methods.</value>
|
||||
public IValueConverter Converter
|
||||
{
|
||||
get { return (IValueConverter)GetValue(ConverterProperty); }
|
||||
set { SetValue(ConverterProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Identifier for the <see cref="Converter" /> dependency property.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty ConverterProperty =
|
||||
DependencyProperty.Register(nameof(Converter), typeof(IValueConverter), typeof(MultiBindingBehavior), new PropertyMetadata(null, OnPropertyChanged));
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets an optional parameter to pass to the converter as additional information.
|
||||
/// </summary>
|
||||
/// <value>A value of the type expected by the converter, which might be an object element or a string depending on the definition and XAML capabilities both of the property type being used and of the implementation of the converter.</value>
|
||||
public object ConverterParameter
|
||||
{
|
||||
get { return GetValue(ConverterParameterProperty); }
|
||||
set { SetValue(ConverterParameterProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Identifier for the <see cref="ConverterParameter" /> dependency property.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty ConverterParameterProperty =
|
||||
DependencyProperty.Register(nameof(ConverterParameter), typeof(object), typeof(MultiBindingBehavior), new PropertyMetadata(null, OnPropertyChanged));
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value that indicates the direction of the data flow in the binding.
|
||||
/// </summary>
|
||||
/// <value>A value that indicates the direction of the data flow in the binding.</value>
|
||||
public BindingMode Mode
|
||||
{
|
||||
get { return (BindingMode)GetValue(ModeProperty); }
|
||||
set { SetValue(ModeProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Identifier for the <see cref="Mode" /> dependency property.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty ModeProperty =
|
||||
DependencyProperty.Register(nameof(Mode), typeof(BindingMode), typeof(MultiBindingBehavior), new PropertyMetadata(BindingMode.OneWay, OnPropertyChanged));
|
||||
|
||||
private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
var multiBindingBehavior = (MultiBindingBehavior)d;
|
||||
|
||||
multiBindingBehavior.Update();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MultiBindingBehavior"/> class.
|
||||
/// </summary>
|
||||
public MultiBindingBehavior()
|
||||
{
|
||||
Items = new MultiBindingItemCollection();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called after the behavior is attached to an AssociatedObject.
|
||||
/// </summary>
|
||||
/// <remarks>Override this to hook up functionality to the AssociatedObject.</remarks>
|
||||
protected override void OnAttached()
|
||||
{
|
||||
base.OnAttached();
|
||||
|
||||
Update();
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (AssociatedObject == null || string.IsNullOrEmpty(PropertyName))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var targetProperty = PropertyName;
|
||||
Type targetType;
|
||||
|
||||
if (targetProperty.Contains("."))
|
||||
{
|
||||
var propertyNameParts = targetProperty.Split('.');
|
||||
|
||||
targetType = Type.GetType(string.Format("Windows.UI.Xaml.Controls.{0}, Windows",
|
||||
propertyNameParts[0]));
|
||||
|
||||
targetProperty = propertyNameParts[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
targetType = AssociatedObject.GetType();
|
||||
}
|
||||
|
||||
PropertyInfo targetDependencyPropertyField = null;
|
||||
|
||||
while (targetDependencyPropertyField == null && targetType != null)
|
||||
{
|
||||
var targetTypeInfo = targetType.GetTypeInfo();
|
||||
|
||||
targetDependencyPropertyField = targetTypeInfo.GetDeclaredProperty(targetProperty + "Property");
|
||||
|
||||
targetType = targetTypeInfo.BaseType;
|
||||
}
|
||||
|
||||
if (targetDependencyPropertyField == null) return;
|
||||
|
||||
var targetDependencyProperty = (DependencyProperty)targetDependencyPropertyField.GetValue(null);
|
||||
|
||||
var binding = new Binding()
|
||||
{
|
||||
Path = new PropertyPath("Value"),
|
||||
Source = Items,
|
||||
Converter = Converter,
|
||||
ConverterParameter = ConverterParameter,
|
||||
Mode = Mode
|
||||
};
|
||||
|
||||
BindingOperations.SetBinding(AssociatedObject, targetDependencyProperty, binding);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
using Windows.UI.Xaml;
|
||||
|
||||
namespace LiveCharts.Uwp.Components.MultiBinding
|
||||
{
|
||||
/// <summary>
|
||||
/// A multiple binding item.
|
||||
/// </summary>
|
||||
public class MultiBindingItem : DependencyObject
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the binding value.
|
||||
/// </summary>
|
||||
/// <value>The binding value.</value>
|
||||
public object Value
|
||||
{
|
||||
get { return GetValue(ValueProperty); }
|
||||
set { SetValue(ValueProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Identifier for the <see cref="Value" /> dependency property.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty ValueProperty =
|
||||
DependencyProperty.Register(nameof(Value), typeof(object), typeof(MultiBindingItem), new PropertyMetadata(null, OnValueChanged));
|
||||
|
||||
private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
var multiBindingItem = (MultiBindingItem)d;
|
||||
|
||||
multiBindingItem.Update();
|
||||
}
|
||||
|
||||
internal MultiBindingItemCollection Parent { get; set; }
|
||||
|
||||
private void Update()
|
||||
{
|
||||
var parent = Parent;
|
||||
|
||||
parent?.Update();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using Windows.UI.Xaml;
|
||||
|
||||
namespace LiveCharts.Uwp.Components.MultiBinding
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a collection of <see cref="MultiBindingBehavior" />.
|
||||
/// </summary>
|
||||
public class MultiBindingItemCollection : DependencyObjectCollection<MultiBindingItem>
|
||||
{
|
||||
private bool _updating;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the multiple binding value.
|
||||
/// </summary>
|
||||
/// <value>The multiple binding value.</value>
|
||||
public object[] Value
|
||||
{
|
||||
get { return (object[])GetValue(ValueProperty); }
|
||||
set { SetValue(ValueProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Identifier for the <see cref="Value" /> dependency property.
|
||||
/// </summary>
|
||||
internal static readonly DependencyProperty ValueProperty =
|
||||
DependencyProperty.Register(nameof(Value), typeof(object[]), typeof(MultiBindingItemCollection), new PropertyMetadata(null, OnValueChanged));
|
||||
|
||||
private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
var multiBindingItemCollection = (MultiBindingItemCollection)d;
|
||||
|
||||
multiBindingItemCollection.UpdateSource();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MultiBindingItemCollection"/> class.
|
||||
/// </summary>
|
||||
public MultiBindingItemCollection()
|
||||
{
|
||||
CollectionChanged += OnCollectionChanged;
|
||||
}
|
||||
|
||||
private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
if (e.OldItems != null)
|
||||
{
|
||||
foreach (MultiBindingItem item in e.OldItems)
|
||||
{
|
||||
item.Parent = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (e.NewItems != null)
|
||||
{
|
||||
foreach (MultiBindingItem item in e.NewItems)
|
||||
{
|
||||
item.Parent = this;
|
||||
}
|
||||
}
|
||||
|
||||
Update();
|
||||
}
|
||||
|
||||
internal void Update()
|
||||
{
|
||||
if (_updating)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_updating = true;
|
||||
|
||||
Value = this
|
||||
.OfType<MultiBindingItem>()
|
||||
.Select(x => x.Value)
|
||||
.ToArray();
|
||||
}
|
||||
finally
|
||||
{
|
||||
_updating = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateSource()
|
||||
{
|
||||
if (_updating)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_updating = true;
|
||||
|
||||
for (var index = 0; index < this.Count; index++)
|
||||
{
|
||||
var multiBindingItem = this[index] as MultiBindingItem;
|
||||
|
||||
if (multiBindingItem != null)
|
||||
{
|
||||
multiBindingItem.Value = Value[index];
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_updating = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Data;
|
||||
|
||||
namespace LiveCharts.Uwp.Components.MultiBinding
|
||||
{
|
||||
/// <summary>
|
||||
/// An <see cref="IValueConverter"/> abstract implementation to be used with the <see cref="MultiBindingBehavior"/>.
|
||||
/// </summary>
|
||||
public abstract class MultiValueConverterBase : DependencyObject, IValueConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Modifies the source data before passing it to the target for display in the UI.
|
||||
/// </summary>
|
||||
/// <returns>The value to be passed to the target dependency property.</returns>
|
||||
/// <param name="values">The source data being passed to the target.</param>
|
||||
/// <param name="targetType">The <see cref="T:System.Type"/> of data expected by the target dependency property.</param>
|
||||
/// <param name="parameter">An optional parameter to be used in the converter logic.</param>
|
||||
/// <param name="culture">The culture of the conversion.</param>
|
||||
public abstract object Convert(object[] values, Type targetType, object parameter, CultureInfo culture);
|
||||
|
||||
/// <summary>
|
||||
/// Modifies the target data before passing it to the source object. This method is called only in <see cref="F:System.Windows.Data.BindingMode.TwoWay"/> bindings.
|
||||
/// </summary>
|
||||
/// <returns>The value to be passed to the source object.</returns>
|
||||
/// <param name="value">The target data being passed to the source.</param>
|
||||
/// <param name="targetType">The <see cref="T:System.Type"/> of data expected by the source object.</param>
|
||||
/// <param name="parameter">An optional parameter to be used in the converter logic.</param>
|
||||
/// <param name="culture">The culture of the conversion.</param>
|
||||
public abstract object[] ConvertBack(object value, Type targetType, object parameter, CultureInfo culture);
|
||||
|
||||
object IValueConverter.Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
var cultureInfo = !string.IsNullOrEmpty(language) ? new CultureInfo(language) : null;
|
||||
|
||||
return Convert((object[])value, targetType, parameter, cultureInfo);
|
||||
}
|
||||
|
||||
object IValueConverter.ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
var cultureInfo = !string.IsNullOrEmpty(language) ? new CultureInfo(language) : null;
|
||||
|
||||
return ConvertBack(value, targetType, parameter, cultureInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user