繁体   English   中英

如何配置控件的click事件处理程序以在创建对象时将其删除?

[英]How can I configure the click event handler of a control for removing itself at its object creation?

假设我有两个类: MainWindowMainWindowViewModel MainWindow有一个名为ButtonControl的控件,带有一个单击事件处理程序,该事件将在MainWindowViewModel中调用一个函数。 该函数创建图像,然后将其添加到MainWindow中的WrapPanel的子级中。 我想在创建图像控件时为它配置一个click事件处理程序,以便在单击它时可以从MainWindow中删除该控件(MouseLeftButtonUp)。 我能怎么做?

MainWindow.xaml

<Windows ...>
<Grid>
<Button Name="ButtonControl" Click="ButtonControl_Click" />
<WrapPanel Name="AttachedPhotosWP" />
</Grid>
</Windows>

MainWindow.xaml.cs

public partial class MainWindow : Window
{
    private MainWindowViewModel _vm = new MainWindowViewModel();
    public MainWindowViewModel VM{ get { return _vm; } set { _vm= value; } }
    public MainWindow()
    {
       InitializeComponent();
       this.DataContext = VM;      
    }
    private void ButtonControl_Click(object sender, MouseButtonEventArgs e)
    {
        VM.ImageCreation(this);
    }
}

MainWindowViewModel.cs

public class MainWindowViewModel
{
    /* Some other codes */


    public void ImageCreation(MainWindow MW)
    {
         OpenFileDialog openFileDialog = new OpenFileDialog();
         openFileDialog.Multiselect = true;
         openFileDialog.Title = "Select Images...";
         if (openFileDialog.ShowDialog() == true)
         {
              foreach (var file in openFileDialog.FileNames)
              {
                  try
                  {
                      Image img = new Image();
                      BitmapImage imgSrc = new BitmapImage();
                      imgSrc.BeginInit();
                      Uri fileUri = new Uri(file, UriKind.Absolute);
                      imgSrc.UriSource = fileUri;
                      imgSrc.DecodePixelWidth = 100;
                      imgSrc.CacheOption = BitmapCacheOption.OnLoad;
                      imgSrc.EndInit();
                      img.Source = imgSrc;
                      img.Stretch = Stretch.Uniform;
                      img.Height = 70;
                      img.Margin = new Thickness(4, 4, 4, 4);
                      img.MouseLeftButtonUp += ????
                      img.Cursor = Cursors.Hand;
                      MW.AttachedPhotosWP.Children.Add(img);
                  }
                  catch (SecurityException ex) { }
                  catch (Exception ex) { }     
              }
          }
    }

}

将MainWindow引用传递给ImageCreation方法并在后面的代码中创建UI元素根本不是MVVM。

基本的MVVM解决方案将使用ItemsControl和包含Image元素的ItemTemplate。 ItemsControl的ItemsSource属性绑定到ObservableCollection<ImageSource> Image元素具有一个事件处理程序,该事件处理程序将自己从该集合中删除。

<ItemsControl ItemsSource="{Binding ImageFiles}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <WrapPanel/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Image Source="{Binding}"
                   Height="70" Margin="4"
                   MouseLeftButtonUp="Image_MouseLeftButtonUp"/>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>
...
<Button Content="Load Images..." Click="LoadButton_Click"/>

MainWindow类和视图模型如下所示:

public partial class MainWindow : Window
{
    private readonly ViewModel viewModel = new ViewModel();

    public MainWindow()
    {
        DataContext = viewModel;
        InitializeComponent();
    }

    private void LoadButton_Click(object sender, RoutedEventArgs e)
    {
        var openFileDialog = new OpenFileDialog();
        openFileDialog.Multiselect = true;
        openFileDialog.Title = "Select Images...";
        openFileDialog.Filter = "JPEG Files (*.jpg)|*.jpg|PNG Files (*.png)|*.png";

        if (openFileDialog.ShowDialog() == true)
        {
            viewModel.LoadImages(openFileDialog.FileNames);
        }
    }

    private void Image_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        var image = (Image)sender;
        viewModel.ImageFiles.Remove(image.Source);
    }
}

public class ViewModel
{
    public ObservableCollection<ImageSource> ImageFiles { get; }
        = new ObservableCollection<ImageSource>();

    public void LoadImages(IEnumerable<string> imageFiles)
    {
        ImageFiles.Clear();

        foreach (var imageFile in imageFiles)
        {
            var image = new BitmapImage();
            image.BeginInit();
            image.UriSource = new Uri(imageFile, UriKind.RelativeOrAbsolute);
            image.DecodePixelWidth = 100;
            image.EndInit();
            ImageFiles.Add(image);
        }
    }
}

您可以通过以下方式进一步改善此效果:使用一个按钮将鼠标事件处理程序替换为Image,该按钮在其ControlTemplate中使用Image元素,并且将其Command属性绑定到视图模型中的ICommand属性。 该命令将从源集合中删除当前图像。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM