gpt4 book ai didi

用于平铺 ListView 的 WPF 工具包

转载 作者:行者123 更新时间:2023-12-03 02:49:20 31 4
gpt4 key购买 nike

我需要创建格式良好的按钮图 block ,例如 Windows 8 开始页面。是否有任何工具包可用于自定义 ListView,它可能支持平铺 View 或 GridView ,具有一些格式设置,并且可能有一些动画选项。

我尝试创建自己的自定义 ListView ,但这似乎是一项复杂的任务。

最佳答案

我不知道有什么好的免费图 block 控件。 DevExpress有一个好看的商业版本。

如果您指定了确切的要求(即您需要配置哪些属性、什么样的动画……)并且我有时间,我会尝试一下。

编辑:我创建了一个带有 WrapPanel 作为 ItemsPanel 的 ItemsControl。使用 MVVM 模式,根据您的需要和数据对象扩展控件应该不会太困难。 DragDrop 行为部分很难做到——当然还有一些改进的空间。我没有包含图像。

enter image description here

TileControl.xaml:

<UserControl x:Class="WpfApplication1.TileControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:local="clr-namespace:WpfApplication1"
xmlns:beh="clr-namespace:WpfApplication1.Behavior"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">

<UserControl.DataContext>
<local:ViewModel />
</UserControl.DataContext>

<UserControl.Resources>
<local:TileTypeToColorConverter x:Key="TileTypeToColorConverter" />
</UserControl.Resources>

<Grid>
<Image Source="/WpfApplication1;component/Themes/background.png" Stretch="UniformToFill" />
<Border x:Name="darkenBorder" Background="Black" Opacity="0.6" />
<ItemsControl ItemsSource="{Binding Tiles}" Background="Transparent" Margin="5">
<i:Interaction.Behaviors>
<beh:ItemsControlDragDropBehavior />
</i:Interaction.Behaviors>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="local:TileModel">
<Button Content="{Binding Text}" Background="{Binding TileType, Converter={StaticResource TileTypeToColorConverter}}"
Command="{Binding ClickCommand}" Width="120" Height="110" Padding="5" RenderTransformOrigin="0.5, 0.5" >
<Button.RenderTransform>
<TransformGroup>
<ScaleTransform />
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</Button.RenderTransform>
<Button.Template>
<ControlTemplate TargetType="Button">
<Border Padding="5" Background="Transparent">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Border x:Name="tileBackground" Grid.RowSpan="2" Background="{TemplateBinding Background}" Opacity="0.9" />
<Image Source="{Binding Image}" HorizontalAlignment="Center" VerticalAlignment="Bottom" Height="50" />
<ContentPresenter TextElement.Foreground="White" Grid.Row="1" HorizontalAlignment="Center" Margin="3,10" />
</Grid>
</Border>
</ControlTemplate>
</Button.Template>
<Button.Resources>
<ElasticEase x:Key="easeOutBounce" EasingMode="EaseOut" Springiness="6" Oscillations="4" />
</Button.Resources>
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard Duration="00:00:00.05" AutoReverse="True">
<DoubleAnimation To="0.1" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)"/>
<DoubleAnimation To="0.1" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)" From="0.1" To="1.0" EasingFunction="{StaticResource easeOutBounce}" />
<DoubleAnimation Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)" From="0.1" To="1.0" EasingFunction="{StaticResource easeOutBounce}" />
<DoubleAnimation Storyboard.TargetProperty="Opacity" From="0.1" To="1.0" EasingFunction="{StaticResource easeOutBounce}" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</UserControl>

ViewModel、TileModel、TileType、ActionCommand:

using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows.Input;
using System.Windows.Media.Imaging;

namespace WpfApplication1
{
public class ViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}

private ObservableCollection<TileModel> _tiles;
public ObservableCollection<TileModel> Tiles { get { return _tiles; } set { _tiles = value; OnPropertyChanged("Tiles"); } }

public ViewModel()
{

Tiles= new ObservableCollection<TileModel>()
{
new TileModel() { Text = "Facebook", Image = Properties.Resources.Facebook.ToBitmapImage(), TileType = TileType.Website },
new TileModel() { Text = "Skype", Image = Properties.Resources.Skype.ToBitmapImage(), TileType = TileType.Application },
new TileModel() { Text = "Ask.com", Image = Properties.Resources.AskCom.ToBitmapImage(), TileType = TileType.Website },
new TileModel() { Text = "Amazon", Image = Properties.Resources.Amazon.ToBitmapImage(), TileType = TileType.Website },
new TileModel() { Text = "Evernote", Image = Properties.Resources.Evernote.ToBitmapImage(), TileType = TileType.Application },
new TileModel() { Text = "Twitter", Image = Properties.Resources.Twitter.ToBitmapImage(), TileType = TileType.Website },
new TileModel() { Text = "Internet Explorer", Image = Properties.Resources.InterneExplorer.ToBitmapImage(), TileType = TileType.Browser },
new TileModel() { Text = "Android", Image = Properties.Resources.Android.ToBitmapImage(), TileType = TileType.Application },
new TileModel() { Text = "Winamp", Image = Properties.Resources.Winamp.ToBitmapImage(), TileType = TileType.Application },
new TileModel() { Text = "YouTube", Image = Properties.Resources.YouTube.ToBitmapImage(), TileType = TileType.Website },
};
}

}


public class TileModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}

private string _text;
public string Text { get { return _text; } set { _text = value; OnPropertyChanged("Text"); } }

private BitmapSource _image;
public BitmapSource Image { get { return _image; } set { _image = value; OnPropertyChanged("Image"); } }

private TileType _tileType;
public TileType TileType { get { return _tileType; } set { _tileType = value; OnPropertyChanged("TileType"); } }

public ICommand ClickCommand { get; private set; }

public TileModel()
{
ClickCommand = new ActionCommand(Click);
}

private void Click()
{
// execute appropriate action
}

}

public enum TileType
{
Browser,
Website,
Application
}

public class ActionCommand : ICommand
{
public event EventHandler CanExecuteChanged;
private Action _action;

public ActionCommand(Action action)
{
_action = action;
}

public bool CanExecute(object parameter) { return true; }

public void Execute(object parameter)
{
if (_action != null)
_action();
}
}
}

ItemsControlDragDropBehavior:

using System;
using System.Collections;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Interactivity;
using System.Windows.Media;

namespace WpfApplication1.Behavior
{
public class ItemsControlDragDropBehavior : Behavior<ItemsControl>
{
private bool _isMouseDown;
private bool _isDragging;
private Point _dragStartPosition;
private UIElement _dragItem;
private UIElement _dragContainer;
private IDataObject _dataObject;
private int _currentDropIndex;
private Point _lastCheckPoint;

protected override void OnAttached()
{
this.AssociatedObject.AllowDrop = true;
this.AssociatedObject.PreviewMouseLeftButtonDown += AssociatedObject_PreviewMouseLeftButtonDown;
this.AssociatedObject.PreviewMouseMove += AssociatedObject_PreviewMouseMove;
this.AssociatedObject.PreviewDragOver += AssociatedObject_PreviewDragOver;
this.AssociatedObject.PreviewDrop += AssociatedObject_PreviewDrop;
this.AssociatedObject.PreviewMouseLeftButtonUp += AssociatedObject_PreviewMouseLeftButtonUp;

base.OnAttached();
}

void AssociatedObject_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
ItemsControl itemsControl = (ItemsControl)sender;
Point p = e.GetPosition(itemsControl);

object data = itemsControl.GetDataObjectFromPoint(p);
_dataObject = data != null ? new DataObject(data.GetType(), data) : null;

_dragContainer = itemsControl.GetItemContainerFromPoint(p);
if (_dragContainer != null)
_dragItem = GetItemFromContainer(_dragContainer);

if (data != null)
{
_isMouseDown = true;
_dragStartPosition = p;
}
}

void AssociatedObject_PreviewMouseMove(object sender, MouseEventArgs e)
{
if (_isMouseDown)
{
ItemsControl itemsControl = (ItemsControl)sender;
Point currentPosition = e.GetPosition(itemsControl);
if ((_isDragging == false) && (Math.Abs(currentPosition.X - _dragStartPosition.X) > SystemParameters.MinimumHorizontalDragDistance) ||
(Math.Abs(currentPosition.Y - _dragStartPosition.Y) > SystemParameters.MinimumVerticalDragDistance))
{
DragStarted(e.GetPosition(itemsControl));
}
e.Handled = true;
}
}

void AssociatedObject_PreviewDragOver(object sender, DragEventArgs e)
{
UpdateDropIndex(e.GetPosition(this.AssociatedObject));
}

void AssociatedObject_PreviewDrop(object sender, DragEventArgs e)
{
UpdateDropIndex(e.GetPosition(this.AssociatedObject));
}

void AssociatedObject_PreviewMouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
_isMouseDown = false;
}

private void DragStarted(Point p)
{
if (!_isDragging)
{
_isDragging = true;

if (_dragContainer != null)
_dragContainer.Opacity = 0.3;

_currentDropIndex = FindDropIndex(p);

DragDropEffects e = DragDrop.DoDragDrop(this.AssociatedObject, _dataObject, DragDropEffects.Copy | DragDropEffects.Move);

ResetState();
}
}

private void ResetState()
{
if (_dragContainer != null)
_dragContainer.Opacity = 1.0;

_isMouseDown = false;
_isDragging = false;
_dataObject = null;
_dragItem = null;
_dragContainer = null;
_currentDropIndex = -1;
}

private void UpdateDropIndex(Point p)
{
if ((_lastCheckPoint - p).Length > SystemParameters.MinimumHorizontalDragDistance) // prevent too frequent call
{
int dropIndex = FindDropIndex(p);
if (dropIndex != _currentDropIndex && dropIndex > -1)
{
this.AssociatedObject.RemoveItem(_dataObject);
this.AssociatedObject.AddItem(_dataObject, dropIndex);
_currentDropIndex = dropIndex;
}
_lastCheckPoint = p;
}
}

private int FindDropIndex(Point p)
{
ItemsControl itemsControl = this.AssociatedObject;
UIElement dropTargetContainer = null;

dropTargetContainer = itemsControl.GetItemContainerFromPoint(p);

int index = -1;
if (dropTargetContainer != null)
{
index = itemsControl.ItemContainerGenerator.IndexFromContainer(dropTargetContainer);

if (!IsPointInTopHalf(p))
index = index++; // in second half of item, add after
}
else if (IsPointAfterAllItems(itemsControl, p))
{
// still within itemscontrol, but after all items
index = itemsControl.Items.Count - 1;
}

return index;
}

public bool IsPointInTopHalf(Point p)
{
ItemsControl itemsControl = this.AssociatedObject;

bool isInTopHalf = false;

UIElement selectedItemContainer = itemsControl.GetItemContainerFromPoint(p);
Point relativePosition = Mouse.GetPosition(selectedItemContainer);

if (IsItemControlOrientationHorizontal())
isInTopHalf = relativePosition.X < ((FrameworkElement)selectedItemContainer).ActualWidth / 2;
else
isInTopHalf = relativePosition.Y < ((FrameworkElement)selectedItemContainer).ActualHeight / 2;

return isInTopHalf;
}

private bool IsItemControlOrientationHorizontal()
{
bool isHorizontal = false;
Panel panel = GetItemsPanel();
if (panel is WrapPanel)
isHorizontal = ((WrapPanel)panel).Orientation == Orientation.Horizontal;
else if (panel is StackPanel)
isHorizontal = ((StackPanel)panel).Orientation == Orientation.Horizontal;

return isHorizontal;
}

private UIElement GetItemFromContainer(UIElement container)
{
UIElement item = null;
if (container != null)
item = VisualTreeHelper.GetChild(container, 0) as UIElement;
return item;
}

private Panel GetItemsPanel()
{
ItemsPresenter itemsPresenter = GetVisualChild<ItemsPresenter>(this.AssociatedObject);
Panel itemsPanel = VisualTreeHelper.GetChild(itemsPresenter, 0) as Panel;
return itemsPanel;
}

private static T GetVisualChild<T>(DependencyObject parent) where T : Visual
{
T child = default(T);

int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < numVisuals; i++)
{
Visual v = (Visual)VisualTreeHelper.GetChild(parent, i);
child = v as T;
if (child == null)
{
child = GetVisualChild<T>(v);
}
if (child != null)
{
break;
}
}
return child;
}

/// still needs some work
private static bool IsPointAfterAllItems(ItemsControl itemsControl, Point point)
{
bool isAfter = false;

UIElement target = itemsControl.GetLastItemContainer();
Point targetPos = target.TransformToAncestor(itemsControl).Transform(new Point(0, 0));
Point relativeToTarget = new Point(point.X - targetPos.X, point.Y - targetPos.Y);

if (relativeToTarget.X >= 0 && relativeToTarget.Y >= 0)
{
var bounds = VisualTreeHelper.GetDescendantBounds(target);
isAfter = !bounds.Contains(relativeToTarget);
}
return isAfter;
}
}

public static class ItemsControlExtensions
{
public static object GetDataObjectFromPoint(this ItemsControl itemsControl, Point p)
{
UIElement element = itemsControl.InputHitTest(p) as UIElement;

while (element != null)
{
if (element == itemsControl)
return null;

object data = itemsControl.ItemContainerGenerator.ItemFromContainer(element);
if (data != DependencyProperty.UnsetValue)
return data;
else
element = VisualTreeHelper.GetParent(element) as UIElement;
}
return null;
}

public static UIElement GetItemContainerFromPoint(this ItemsControl itemsControl, Point p)
{
UIElement element = itemsControl.InputHitTest(p) as UIElement;

while (element != null)
{
object data = itemsControl.ItemContainerGenerator.ItemFromContainer(element);

if (data != DependencyProperty.UnsetValue)
return element;
else
element = VisualTreeHelper.GetParent(element) as UIElement;
}

return element;
}

public static UIElement GetLastItemContainer(this ItemsControl itemsControl)
{
UIElement container = null;
if (itemsControl.HasItems)
container = itemsControl.GetItemContainerAtIndex(itemsControl.Items.Count - 1);

return container;
}

public static UIElement GetItemContainerAtIndex(this ItemsControl itemsControl, int index)
{
UIElement container = null;

if (itemsControl != null && itemsControl.Items.Count > index && itemsControl.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated)
container = itemsControl.ItemContainerGenerator.ContainerFromIndex(index) as UIElement;
else
container = itemsControl;

return container;
}

public static void AddItem(this ItemsControl itemsControl, IDataObject item, int insertIndex)
{
if (itemsControl.ItemsSource != null)
{
foreach (string format in item.GetFormats())
{
object data = item.GetData(format);
IList iList = itemsControl.ItemsSource as IList;
if (iList != null)
iList.Insert(insertIndex, data);
else
{
Type type = itemsControl.ItemsSource.GetType();
Type genericList = type.GetInterface("IList`1");
if (genericList != null)
type.GetMethod("Insert").Invoke(itemsControl.ItemsSource, new object[] { insertIndex, data });
}
}
}
else
itemsControl.Items.Insert(insertIndex, item);
}

public static void RemoveItem(this ItemsControl itemsControl, IDataObject itemToRemove)
{
if (itemToRemove != null)
{
foreach (string format in itemToRemove.GetFormats())
{
object data = itemToRemove.GetData(format);
int index = itemsControl.Items.IndexOf(data);
if (index > -1)
itemsControl.RemoveItemAt(index);
}
}
}

public static void RemoveItemAt(this ItemsControl itemsControl, int removeIndex)
{
if (removeIndex != -1 && removeIndex < itemsControl.Items.Count)
{
if (itemsControl.ItemsSource != null)
{
IList iList = itemsControl.ItemsSource as IList;
if (iList != null)
{
iList.RemoveAt(removeIndex);
}
else
{
Type type = itemsControl.ItemsSource.GetType();
Type genericList = type.GetInterface("IList`1");
if (genericList != null)
type.GetMethod("RemoveAt").Invoke(itemsControl.ItemsSource, new object[] { removeIndex });
}
}
else
itemsControl.Items.RemoveAt(removeIndex);
}
}
}
}

TileTypeToColorConverter:

public class TileTypeToColorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
SolidColorBrush brush = new SolidColorBrush();
TileType type = (TileType)value;
switch (type)
{
case TileType.Browser: brush.Color = Colors.Maroon; break;
case TileType.Application: brush.Color = Colors.DodgerBlue; break;
case TileType.Website: brush.Color = Colors.DarkGoldenrod; break;
}
return brush;
}

public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}

关于用于平铺 ListView 的 WPF 工具包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15652597/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com