WPF 添加图片,可移动图片位置

发布时间 2023-09-18 09:42:41作者: 潇潇烟雨

1、创建一个.xaml文件,页面布局:

<UserControl x:Class="Module.ScreentView"
             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:local="clr-namespace:Module.ScreentView"
             xmlns:prism="clr-namespace:Wpf.Services.Dialogs;assembly=Wpf"             
             xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
             xmlns:controls="clr-namespace:Controls.Controls;assembly=Controls"
             xmlns:converts="clr-namespace:Controls.Converters;assembly=Controls"
             xmlns:cache="clr-namespace:Controls.Controls.CacheImage;assembly=Controls"
             xmlns:ac="clr-namespace:Controls.Controls.Attach;assembly=Controls"
             mc:Ignorable="d" 
             d:DesignHeight="1080" d:DesignWidth="1920" FontSize="32" Loaded="UserControl_Loaded">

    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Loaded">
            <i:InvokeCommandAction Command="{Binding LoadCmd}"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>

 <prism:Dialog.WindowStyle>
        <Style TargetType="Window">
            <Setter Property="ShowInTaskbar" Value="False"/>
            <Setter Property="WindowStyle" Value="None"/>
            <Setter Property="WindowState" Value="Maximized"/>
            <Setter Property="AllowsTransparency" Value="True"/>
            <Setter Property="Background" Value="Transparent"/>
            <Setter Property="ResizeMode" Value="NoResize"/>
        </Style>
    </prism:Dialog.WindowStyle>

<UserControl.Resources>
        <converts:Bool2VisibilityConverter x:Key="Bool2VisibilityConverter"/>
        <converts:String2VisibilityReConverter x:Key="String2VisibilityReConverter"/>
        <converts:String2VisibilityConverter x:Key="String2VisibilityConverter"/>
        <converts:String2BitmapUrlConverter x:Key="String2BitmapUrlConverter"/>
        <Style TargetType="{x:Type cache:CacheImage}">
            <Setter Property="HorizontalAlignment" Value="Center"/>
            <Setter Property="VerticalAlignment" Value="Center"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type cache:CacheImage}">
                        <Border Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}"
                            HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
                            VerticalAlignment="{TemplateBinding VerticalAlignment}">
                            <Grid>
                                <Image x:Name="image" Stretch="{TemplateBinding Stretch}" RenderOptions.BitmapScalingMode="HighQuality"/>
                                <TextBlock x:Name="txtLoading" Text="{TemplateBinding LoadingText}"
                                       FontSize="32"
                                       FontFamily="{TemplateBinding FontFamily}"
                                       FontWeight="{TemplateBinding FontWeight}"
                                       Foreground="{TemplateBinding Foreground}"
                                       HorizontalAlignment="Center"
                                       VerticalAlignment="Center"/>
                            </Grid>
                        </Border>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsLoading" Value="False">
                                <Setter Property="Visibility" Value="Collapsed" TargetName="txtLoading"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
        <Style x:Key="ImgeListBoxStyle" TargetType="{x:Type ListBox}">
            <Setter Property="Background" Value="Transparent" />
            <Setter Property="BorderThickness" Value="0"/>
            <Setter Property="Focusable" Value="False"/>
            <Setter Property="FontSize" Value="20"/>
            <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
            <Setter Property="Foreground" Value="{DynamicResource MainTextForBrush}"/>
            <Setter Property="SnapsToDevicePixels" Value="True" />
            <Setter Property="HorizontalContentAlignment" Value="Stretch" />
            <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled" />
            <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Hidden"/>
            <Setter Property="ScrollViewer.CanContentScroll" Value="False"/>
            <Setter Property="ScrollViewer.PanningMode" Value="Both"/>
            <Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
            <Setter Property="VirtualizingStackPanel.IsVirtualizing" Value="False"/>
            <Setter Property="ItemsPanel">
                <Setter.Value>
                    <ItemsPanelTemplate>
                        <controls:UniformSpacingPanel Spacing="20" ItemWidth="435" ItemHeight="326.25" Orientation="Horizontal" ChildWrapping="Wrap" IsItemsHost="True"/>
                    </ItemsPanelTemplate>
                </Setter.Value>
            </Setter>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="ListBox">
                        <Border CornerRadius="8" Background="Transparent">
                            <ScrollViewer >
                                <ItemsPresenter/>
                            </ScrollViewer>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <Setter Property="ItemContainerStyle">
                <Setter.Value>
                    <Style TargetType="ListBoxItem">
                        <Setter Property="FocusVisualStyle" Value="{x:Null}" />
                        <Setter Property="SnapsToDevicePixels" Value="True" />
                        <Setter Property="Focusable" Value="True"/>
                        <Setter Property="Template">
                            <Setter.Value>
                                <ControlTemplate TargetType="{x:Type ListBoxItem}">
                                    <controls:SimplePanel Background="{DynamicResource BlockSecondBackBrush}" >
                                        <!--添加按钮-->
                                        <Button Command="{Binding DataContext.AddImageCmd,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ListBox}}" 
                                                Focusable="False" FocusVisualStyle="{x:Null}" Background="{DynamicResource BlockSecondBackBrush}" Visibility="{Binding ImgPath,Converter={StaticResource String2VisibilityReConverter}}">
                                            <Button.Style>
                                                <Style  TargetType="Button">
                                                    <Setter Property="OverridesDefaultStyle" Value="True" />
                                                    <Setter Property="Template">
                                                        <Setter.Value>
                                                            <ControlTemplate TargetType="Button">
                                                                <Border Name="border" BorderThickness="0" BorderBrush="Transparent" Background="{TemplateBinding Background}">
                                                                    <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
                                                                </Border>
                                                            </ControlTemplate>
                                                        </Setter.Value>
                                                    </Setter>
                                                </Style>
                                            </Button.Style>
                                            <controls:SimpleStackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
                                                <Path Data="{DynamicResource ImgAddGeometry}" Width="28" Height="28" Fill="{DynamicResource MainStressForBrush}"/>
                                                <TextBlock Text="添加图片" FontSize="28" Foreground="{DynamicResource MainStressForBrush}" Margin="0,20,0,0"/>
                                                <TextBlock Text="推荐尺寸:1360*1020" FontSize="24" Foreground="{DynamicResource MainTextForBrush}" Margin="0,10,0,0"/>
                                            </controls:SimpleStackPanel>
                                        </Button>
                                        <!--图片-->
                                        <controls:SimplePanel Visibility="{Binding ImgPath,Converter={StaticResource String2VisibilityConverter}}">
                                            <!--<Image Source="{Binding ImgPath,Converter={StaticResource String2BitmapUrlConverter}}" Stretch="UniformToFill" HorizontalAlignment="Center" VerticalAlignment="Center"/>-->
                                            <cache:CacheImage UrlSource="{Binding ImgPath}" Stretch="Fill" LoadingText="图片正在加载中" HorizontalAlignment="Center" VerticalAlignment="Center"/>
                                            <Border Width="48" Height="48" Background="#60000000" CornerRadius="25" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="0,0,10,10">
                                                <Button Width="48" Height="48" Focusable="False" FocusVisualStyle="{x:Null}" Background="Transparent" CommandParameter="{Binding ImgPath}"
                                                    Command="{Binding DataContext.BtnDeleteCmd,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ListBox}}" >
                                                    <Path Width="26.67" Height="26.67" Fill="White" Data="{StaticResource DeleteGeometry}"/>
                                                </Button>
                                            </Border>
                                        </controls:SimplePanel>
                                    </controls:SimplePanel>
                                </ControlTemplate>
                            </Setter.Value>
                        </Setter>
                    </Style>
                </Setter.Value>
            </Setter>
        </Style>
        <Style x:Key="ImgeListBoxStyle2" TargetType="{x:Type ListBox}">
            <Setter Property="Background" Value="Transparent" />
            <Setter Property="BorderThickness" Value="0"/>
            <Setter Property="Focusable" Value="False"/>
            <Setter Property="FontSize" Value="20"/>
            <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
            <Setter Property="Foreground" Value="{DynamicResource MainTextForBrush}"/>
            <Setter Property="SnapsToDevicePixels" Value="True" />
            <Setter Property="HorizontalContentAlignment" Value="Stretch" />
            <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled" />
            <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Hidden"/>
            <Setter Property="ScrollViewer.CanContentScroll" Value="False"/>
            <Setter Property="ScrollViewer.PanningMode" Value="Both"/>
            <Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
            <Setter Property="VirtualizingStackPanel.IsVirtualizing" Value="False"/>
            <Setter Property="ItemsPanel">
                <Setter.Value>
                    <ItemsPanelTemplate>
                        <controls:UniformSpacingPanel Spacing="20" ItemWidth="435" ItemHeight="326.25" Orientation="Horizontal" ChildWrapping="Wrap" IsItemsHost="True"/>
                    </ItemsPanelTemplate>
                </Setter.Value>
            </Setter>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="ListBox">
                        <Border CornerRadius="8" Background="Transparent">
                            <ScrollViewer >
                                <ItemsPresenter/>
                            </ScrollViewer>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <Setter Property="ItemContainerStyle">
                <Setter.Value>
                    <Style TargetType="ListBoxItem">
                        <Setter Property="FocusVisualStyle" Value="{x:Null}" />
                        <Setter Property="SnapsToDevicePixels" Value="True" />
                        <Setter Property="Focusable" Value="True"/>
                        <Setter Property="Template">
                            <Setter.Value>
                                <ControlTemplate TargetType="{x:Type ListBoxItem}">
                                    <controls:SimplePanel Background="{DynamicResource BlockSecondBackBrush}" >
                                        <!--添加按钮-->
                                        <Button Command="{Binding DataContext.AddMiniImageCmd,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ListBox}}" 
                                                Focusable="False" FocusVisualStyle="{x:Null}" Background="{DynamicResource BlockSecondBackBrush}" Visibility="{Binding ImgPath,Converter={StaticResource String2VisibilityReConverter}}">
                                            <Button.Style>
                                                <Style  TargetType="Button">
                                                    <Setter Property="OverridesDefaultStyle" Value="True" />
                                                    <Setter Property="Template">
                                                        <Setter.Value>
                                                            <ControlTemplate TargetType="Button">
                                                                <Border Name="border" BorderThickness="0" BorderBrush="Transparent" Background="{TemplateBinding Background}">
                                                                    <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
                                                                </Border>
                                                            </ControlTemplate>
                                                        </Setter.Value>
                                                    </Setter>
                                                </Style>
                                            </Button.Style>
                                            <controls:SimpleStackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
                                                <Path Data="{DynamicResource ImgAddGeometry}" Width="28" Height="28" Fill="{DynamicResource MainTextForBrush}"/>
                                                <TextBlock Text="添加图片" FontSize="28" Foreground="{DynamicResource MainTextForBrush}" Margin="0,20,0,0"/>
                                            </controls:SimpleStackPanel>
                                        </Button>
                                        <!--图片-->
                                        <controls:SimplePanel Visibility="{Binding ImgPath,Converter={StaticResource String2VisibilityConverter}}">
                                            <!--<Image Source="{Binding ImgPath,Converter={StaticResource String2BitmapUrlConverter}}" Stretch="UniformToFill" HorizontalAlignment="Center" VerticalAlignment="Center"/>-->
                                            <cache:CacheImage UrlSource="{Binding ImgPath}" Stretch="Fill" LoadingText="图片正在加载中" HorizontalAlignment="Center" VerticalAlignment="Center"/>
                                            <Border Width="48" Height="48" Background="#60000000" CornerRadius="25" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="0,0,10,10">
                                                <Button Width="48" Height="48" Focusable="False" FocusVisualStyle="{x:Null}" Background="Transparent" CommandParameter="{Binding ImgPath}"
                                                    Command="{Binding DataContext.BtnDeleteMiniCmd,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ListBox}}" >
                                                    <Path Width="26.67" Height="26.67" Fill="White" Data="{StaticResource DeleteGeometry}"/>
                                                </Button>
                                            </Border>
                                        </controls:SimplePanel>
                                    </controls:SimplePanel>
                                </ControlTemplate>
                            </Setter.Value>
                        </Setter>
                    </Style>
                </Setter.Value>
            </Setter>
        </Style>
    </UserControl.Resources>

<Viewbox>
<Grid x:Name="grid" Width="1440" Height="1080" Background="{DynamicResource PageBackBrush}">

<!--添加图片模式 -->
                <ListBox x:Name="imglist" ItemsSource="{Binding ImgList}" Style="{StaticResource ImgeListBoxStyle}" FocusVisualStyle="{x:Null}" Margin="40" 
                     PreviewMouseMove="ListBox_PreviewMouseMove" Drop="ListBox_Drop" AllowDrop="True" Visibility="{Binding IsSetImg,Converter={StaticResource Bool2VisibilityConverter}}"/>
                <ListBox x:Name="listbox2" ItemsSource="{Binding MiniList}" Style="{StaticResource ImgeListBoxStyle2}" FocusVisualStyle="{x:Null}" Margin="40"
                 Visibility="{Binding IsSetMiniImg,Converter={StaticResource Bool2VisibilityConverter}}"/>

</Grid>
</Viewbox>

 

2、.xaml.cs文件内容

private void ListBox_PreviewMouseMove(object sender, MouseEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed)
            {
                var pos = e.GetPosition(imglist);
                HitTestResult result = VisualTreeHelper.HitTest(imglist, pos);
                if (result == null)
                {
                    return;
                }
                var listBoxItem = GetChildHelper.FindVisualParent<ListBoxItem>(result.VisualHit);
                if (listBoxItem == null || listBoxItem.Content != imglist.SelectedItem)
                {
                    return;
                }
                DataObject dataObj = new DataObject(listBoxItem.Content as ImageFileModel);
                DragDrop.DoDragDrop(imglist, dataObj, DragDropEffects.Move);
            }
        }

private void ListBox_Drop(object sender, DragEventArgs e)
        {
            var pos = e.GetPosition(imglist);
            var result = VisualTreeHelper.HitTest(imglist, pos);
            if (result == null)
            {
                return;
            }

            //查找元数据
            var sourcePerson = e.Data.GetData(typeof(ImageFileModel)) as ImageFileModel;
            if (sourcePerson == null || string.IsNullOrEmpty(sourcePerson.ImgPath))
            {
                return;
            }
            //查找目标数据
            var listBoxItem = GetChildHelper.FindVisualParent<ListBoxItem>(result.VisualHit);
            if (listBoxItem == null)
            {
                return;
            }
            var targetPerson = listBoxItem.Content as ImageFileModel;
            if (ReferenceEquals(targetPerson, sourcePerson) || targetPerson == null || string.IsNullOrEmpty(targetPerson.ImgPath))
            {
                return;
            }

            int sourceIndex = imglist.Items.IndexOf(sourcePerson);
            int targetIndex = imglist.Items.IndexOf(targetPerson);
            if (sourceIndex < targetIndex)  //从上面移动到下面
            {
                if (vm?.ImgList != null)
                {
                    vm?.ImgList.Remove(sourcePerson);
                    vm?.ImgList.Insert(vm.ImgList.IndexOf(targetPerson) + 1, sourcePerson);
                    vm?.ImgArray.Remove(sourcePerson.ImgPath);
                    vm?.ImgArray.Insert(vm.ImgArray.IndexOf(targetPerson.ImgPath) + 1, sourcePerson.ImgPath);
                }
            }
            else if (sourceIndex > targetIndex)
            {
                if (vm?.ImgList != null)
                {
                    vm?.ImgList.Remove(sourcePerson);
                    vm?.ImgList.Insert(vm.ImgList.IndexOf(targetPerson), sourcePerson);
                    vm?.ImgArray.Remove(sourcePerson.ImgPath);
                    vm?.ImgArray.Insert(vm.ImgArray.IndexOf(targetPerson.ImgPath), sourcePerson.ImgPath);
                }
            }
        }


public static T FindVisualParent<T>(DependencyObject obj) where T : class
        {
            while (obj != null)
            {
                if (obj is T)
                    return obj as T;

                obj = VisualTreeHelper.GetParent(obj);
            }
            return null;
        }

  

3、ViewModel.cs

private ObservableCollection<ImageFileModel> _imgList = new ObservableCollection<ImageFileModel>();
public ObservableCollection<ImageFileModel> ImgList
{
get { return _imgList; }
set
{
_imgList = value;
OnPropertyChanged(nameof(ImgList));
}
}



private List<string> _imgArray = new List<string>();
public List<string> ImgArray
{
get { return _imgArray; }
set { _imgArray = value; OnPropertyChanged(nameof(ImgArray)); }
}

public void LoadDualscreenInfo(string position = null)
{

  

MiniImge = result.Data?.mini_pro_image;
ImgArray = result.Data?.images;
if (ImgArray == null)
{
ImgArray = new System.Collections.Generic.List<string>();
}
ImgList.Clear();

//小于10张显示添加按钮
if (ImgArray == null || ImgArray?.Count < 10)
ImgList.Add(new ImageFileModel() { });

for (int i = 0; i < ImgArray?.Count; i++)
{
ImgList.Add(new ImageFileModel() { ImgPath = ImgArray[i] });
}

SetBtnText();

}



 

/// <summary>
/// 设置按钮文本
/// </summary>
private void SetBtnText()
{
if (ImgList != null && ImgList.Count > 1)
{

if (string.IsNullOrEmpty(ImgList.FirstOrDefault().ImgPath))
ImgTextDoubleScreen = "添加图片 +" + (ImgList.Count - 1).ToString();
else
ImgTextDoubleScreen = "添加图片 +" + ImgList.Count.ToString();
}
else
ImgTextDoubleScreen = "添加图片";
}

/// <summary>
        /// 添加图片
        /// </summary>
        private void AddImageMethod()
        {
            OpenFileDialog dlg = new OpenFileDialog();
            dlg.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);
            dlg.Filter = "Image files (*.png;*.jpg;*.jpeg)|*.png;*.jpg;*.jpeg|All files (*.*)|*.*";
            dlg.RestoreDirectory = true;
            if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                var result = dataService.UploadImgFile(GlobalClass.User.Token, GetByteData(dlg.FileName), dlg.SafeFileName);
                if (result?.Code == Model.Responses.CodeType.Success)
                {
                    ImgArray.Add(result.Data);
                    ImgList.Add(new ImageFileModel() { ImgPath = result.Data });
                    if (ImgList.Count == 11)
                        ImgList.Remove(ImgList.FirstOrDefault(p => string.IsNullOrEmpty(p.ImgPath)));
                }
                else
                {
                    IsShowTip = false;
                    IsShowTip = true;
                    TipTxt = !string.IsNullOrEmpty(result?.Message) ? result?.Message : "添加失败";
                    IconType = Models.IconType.warn;
                }
            }
        }

        private byte[] GetByteData(string path)
        {
            using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                byte[] buffer = new byte[fs.Length];
                fs.Read(buffer, 0, buffer.Length);
                fs.Close();
                fs.Dispose();
                return buffer;
            }
        }

        /// <summary>
        /// 删除图片
        /// </summary>
        private void BtnDeleteMethod(string path)
        {
            if (ImgList?.Count == 10 && ImgList.FirstOrDefault(p => string.IsNullOrEmpty(p.ImgPath)) == null)
                ImgList.Insert(0, new ImageFileModel() { });

            ImgArray?.Remove(path);
            ImgList?.Remove(ImgList.FirstOrDefault(p => p.ImgPath == path));
        }

  

public class ImageFileModel
{
  public string ImgPath { get; set; }
}