我有一个 ListView ,上面有一些图像,我希望这样工作:
我使用命令和 CommandParameter 将 ListView 发送到 View-Model ,然后操作<每张图片的em> width 和 height :
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding MVM.SelectedChangedCommand}" CommandParameter="{Binding ElementName=listView}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
视图模型:
private void SelectedChangedAction(object param)
{
ListView s = (ListView)param;
double j = 1;
for (int i = s.SelectedIndex - 1; i >= 0 && j >= 0; i--, j -= 0.15)
{
Pic t = (Pic)s.Items[i];
t.Width = 150 * j;
t.Height = 250 * j;
}
j = 1;
for (int i = s.SelectedIndex + 1; i < s.Items.Count && j >= 0; i++, j -= 0.15)
{
Pic t = (Pic)s.Items[i];
t.Width = 150 * j;
t.Height = 250 * j;
}
s.ScrollIntoView(s.Items[s.SelectedIndex]);
}
但正如我所说,您可以在 View-Model 中看到,我在 VM 中使用了 ListView ,我认为这是违规行为!那么我怎么能在 MVVM 中做这样的事情呢? (当然我认为我可以构建一个基于ListView的新控制器,可以做到这一点,虽然我需要像XAML这样的简单解决方案)
答案 0 :(得分:1)
在ViewModel中为SelectedItem创建一个属性。将其绑定在View的ListView中。使用转换器设置绑定高度和宽度,并将所有逻辑移到那里。
答案 1 :(得分:1)
虽然您已经接受了解决方案,但我发现这个问题很有趣,所以我找到了以下解决方案:
<强> XAML:强>
<Window x:Class="SO40564064.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:SO40564064"
mc:Ignorable="d"
Title="MainWindow" Height="500" Width="600">
<Grid>
<ListView Name="TheView" ItemsSource="{Binding Images}">
<ListView.ItemTemplate>
<DataTemplate>
<local:MyImageBorder Width="{Binding Width}"
Height="{Binding Height}"
Background="{Binding Color}"
IsMouseOverMe="{Binding MouseIsOverMe, Mode=TwoWay}" />
</DataTemplate>
</ListView.ItemTemplate>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"></StackPanel>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>
</Grid>
</Window>
代码背后:
namespace SO40564064
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new ViewModel();
}
}
}
<强>视图模型:强>
public class ViewModel : INotifyPropertyChanged
{
public ViewModel()
{
m_images = new ObservableCollection<MyImage>(
new MyImage[] {
new MyImage() { Color = Brushes.Red, Height = 100, Width = 70 },
new MyImage() { Color = Brushes.Green, Height = 100, Width = 70 },
new MyImage() { Color = Brushes.Blue, Height = 100, Width = 70 },
new MyImage() { Color = Brushes.Yellow, Height = 100, Width = 70 },
new MyImage() { Color = Brushes.Magenta, Height = 100, Width = 70 },
new MyImage() { Color = Brushes.Cyan, Height = 100, Width = 70 }
});
foreach (var image in m_images)
{
image.PropertyChanged += Image_PropertyChanged;
}
}
private void Image_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case "MouseIsOverMe":
var curImage = sender as MyImage;
var curIndex = m_images.IndexOf(curImage);
if (curImage.MouseIsOverMe)
{
if (curIndex > 0)
{
m_images[curIndex - 1].Width *= 1.2;
m_images[curIndex - 1].Height *= 1.2;
}
if (curIndex < m_images.Count - 2)
{
m_images[curIndex + 1].Width *= 1.2;
m_images[curIndex + 1].Height *= 1.2;
}
m_images[curIndex].Width *= 1.5;
m_images[curIndex].Height *= 1.5;
}
else
{
if (curIndex > 0)
{
m_images[curIndex - 1].Width /= 1.2;
m_images[curIndex - 1].Height /= 1.2;
}
if (curIndex < m_images.Count - 2)
{
m_images[curIndex + 1].Width /= 1.2;
m_images[curIndex + 1].Height /= 1.2;
}
m_images[curIndex].Width /= 1.5;
m_images[curIndex].Height /= 1.5;
}
break;
default:
break;
}
}
private ObservableCollection<MyImage> m_images;
public ObservableCollection<MyImage> Images
{
get { return m_images; }
set
{
m_images = value;
OnPropertyChanged("Images");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string property)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
}
}
图片ViewModel类:
public class MyImage : INotifyPropertyChanged
{
private double m_width;
public double Width
{
get { return m_width; }
set
{
m_width = value;
OnPropertyChanged("Width");
}
}
private double m_height;
public double Height
{
get { return m_height; }
set
{
m_height = value;
OnPropertyChanged("Height");
}
}
private Brush m_color;
public Brush Color
{
get { return m_color; }
set
{
m_color = value;
OnPropertyChanged("Color");
}
}
private bool m_mouseIsOverMe;
public bool MouseIsOverMe
{
get { return m_mouseIsOverMe; }
set
{
m_mouseIsOverMe = value;
OnPropertyChanged("MouseIsOverMe");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string property)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
}
}
<强>&#34;图像&#34; Control Subclass(这里是Border子类):
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
namespace SO40564064
{
public class MyImageBorder : Border
{
public MyImageBorder()
{
IsMouseDirectlyOverChanged += MyImageBorder_IsMouseDirectlyOverChanged;
}
public bool IsMouseOverMe
{
get { return (bool)GetValue(IsMouseOverMeProperty); }
set { SetValue(IsMouseOverMeProperty, value); }
}
public static readonly DependencyProperty IsMouseOverMeProperty =
DependencyProperty.Register("IsMouseOverMe", typeof(bool), typeof(MyImageBorder), new PropertyMetadata(false));
private void MyImageBorder_IsMouseDirectlyOverChanged(object sender, System.Windows.DependencyPropertyChangedEventArgs e)
{
IsMouseOverMe = (bool)e.NewValue;
}
}
}
为了我自己的方便,我已经将一个边框子类化,你可以将一个图像子类化(或者你可以包装图像的东西)。
当鼠标悬停在每个图像上时,解决方案仍然有效 - 而不是在选择图像时。您可以使用自定义样式将悬停元素的丑陋默认边框设置为样式。
答案 2 :(得分:0)
您真的不应该直接操作视图模型中的视图组件。相反,应该通过编写自定义布局面板来实现此机制,该面板执行视图中元素的大小调整。 This page有一些关于如何实现这一目标的好信息。