Подскажите, пожалуйста, как можно реализовать большое количество кнопок с одинаковыми двумя изменяющимися картинками так, чтобы не писать для каждой кнопки свойство и команду(автоматизация, так сказать).И желательно, чтоб соблюдался MVVM.
Пример кода
Разметка XAML:
<Window x:Class="TestWPF.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:TestWPF"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<Style x:Key="image">
<Style.Triggers>
<DataTrigger Binding="{Binding IsFirstImage}" Value="False">
<Setter Property="Image.Source" Value="Resources/image1.png" />
</DataTrigger>
<DataTrigger Binding="{Binding IsFirstImage}" Value="True">
<Setter Property="Image.Source" Value="Resources/image2.png" />
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Border>
<Canvas>
<Button x:Name="button1" Width="41" Height="38" Opacity="1" Command="{Binding ToggleCommand}" Canvas.Left="150" Canvas.Top="146">
<Image x:Name="Qwe1" Style="{StaticResource ResourceKey=image}" Width="41" Height="37"/>
</Button>
<Button x:Name="button2" Width="41" Height="38" Opacity="1" Command="{Binding ToggleCommand}" Canvas.Left="100" Canvas.Top="146">
<Image x:Name="Qwe2" Style="{StaticResource ResourceKey=image}" Width="41" Height="37"/>
</Button>
<Button x:Name="button3" Width="41" Height="38" Opacity="1" Command="{Binding ToggleCommand}" Canvas.Left="200" Canvas.Top="146">
<Image x:Name="Qwe3" Style="{StaticResource ResourceKey=image}" Width="41" Height="37"/>
</Button>
</Canvas>
</Border>
</Window>
И моя VM:
namespace TestWPF
{
class ViewModel : INotifyPropertyChanged
{
private bool isFirstImage;
public bool IsFirstImage
{
get { return isFirstImage; }
set { isFirstImage = value; OnPropertyChanged("IsFirstImage"); }
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName]string prop = "")
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(prop));
}
private RelayCommand toggleCommand;
public RelayCommand ToggleCommand
{
get
{
return toggleCommand ??
(toggleCommand = new RelayCommand(obj =>
{
IsFirstImage = !IsFirstImage;
}));
}
}
}
}
Вот у меня три кнопки, все три кнопки изначально при запуске приложения имеют image1, нужно, чтобы при нажатии на определенную кнопку менялась картинка этой же кнопки, на которую нажал (в данный момент у меня при нажатии на любую кнопку меняются картинки на всех кнопках одновременно, оно и понятно, ведь биндинг к одному и тому же свойству). Подскажите, как написать грамотней код, чтобы к каждой кнопке не прописывать отдельное свойство и отдельную команду. Ведь будет неудобно писать для 100 кнопок 100 свойств, 100 команд и 100 привязок в разметке.
BindingList или ObservableCollection, ибо они имеют реализацию INotifyCollectionChanged.Исходя из этого вы можете сделать следующее:
Создаем коллекцию:
public ObservableCollection<ViewModel> Items { get; }
ViewModel - это ваш класс со свойствами для кнопки.
get; - нам по сути надо получить только из нее элементы, не инициализируя ее постоянно, по этому тут нет set;.
Инициализируем коллекцию и заполняем.
public MainViewModel()
{
Items = new ObservableCollection<ViewModel>
{
new ViewModel() //Задаем нужные свойства если надо.
};
}
Вы в любой момент можете написать Items.Add(...).
Переделываем XAML:
Меняем
<Canvas>
<Button x:Name="button1" Width="41" Height="38" Opacity="1" Command="{Binding ToggleCommand}" Canvas.Left="150" Canvas.Top="146">
<Image x:Name="Qwe1" Style="{StaticResource ResourceKey=image}" Width="41" Height="37"/>
</Button>
<Button x:Name="button2" Width="41" Height="38" Opacity="1" Command="{Binding ToggleCommand}" Canvas.Left="100" Canvas.Top="146">
<Image x:Name="Qwe2" Style="{StaticResource ResourceKey=image}" Width="41" Height="37"/>
</Button>
<Button x:Name="button3" Width="41" Height="38" Opacity="1" Command="{Binding ToggleCommand}" Canvas.Left="200" Canvas.Top="146">
<Image x:Name="Qwe3" Style="{StaticResource ResourceKey=image}" Width="41" Height="37"/>
</Button>
</Canvas>
На
<ItemsControl ItemsSource="{Binding Items}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Width="41" Height="38" Command="{Binding ToggleCommand}">
<Image Style="{StaticResource ResourceKey=image}" Width="41" Height="37"/>
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Тут как видите все лишнее убрано, используется ItemsControl, который привязан к коллекции Items. В качестве ItemsPanel задан WrapPanel (тут смотрите сами, как кнопки будут размещаться). Также переопределен шаблон ItemTemplate, в него переехала ваша кнопка.
Вот собственно и все, у вас должно будет вывести всю коллекцию Items с заданным шаблоном.
P.S. Код писал на коленке, так что могут быть неточности.
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости