Подскажите,пожалуйста, у меня имеется класс кнопки:
public class Button : INotifyPropertyChanged
{
public int Left { get; }
public int Top { get; }
public Button(int left, int top)
{
Left = left;
Top = top;
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName]string prop = "")
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(prop));
}
private bool isState;
public bool IsState
{
get
{
return isState;
}
set
{
isState = value;
OnPropertyChanged("IsState");
}
}
}
Имеется VM для кнопок, в котором находятся а)список с инициализацией восьми кнопок:
public ObservableCollection<Button> Buttons { get; } = new ObservableCollection<Button>
{
new Button(437, 153), // Button[0]
new Button(396, 248), // Button[1]
new Button(558, 250), // Button[2]
new Button(661, 253), // Button[3]
new Button(267, 246), // Button[4]
new Button(873, 252), // Button[5]
new Button(667, 505), // Button[6]
new Button(875, 506), // Button[7]
};
б) одна команда для изменения состояния каждой кнопки, в зависимости какую нажать:
private RelayCommand stateCommand;
public RelayCommand StateCommand
{
get
{
return stateCommand ??
(stateCommand = new RelayCommand(obj =>
{
ChangeState((Button)obj);
}));
}
}
в) сам метод ChangeState, который меняет состояние кнопки:
void ChangeState(Button button)
{
button.IsState = !button.IsState;
}
А реализация коллекции кнопок в View сделана таким образом:
<ItemsControl ItemsSource="{Binding Buttons}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Left" Value="{Binding Left}"/>
<Setter Property="Canvas.Top" Value="{Binding Top}"/>
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Button Width="48" Command="{Binding DataContext.StateCommand, ElementName=mainWindow}" CommandParameter="{Binding}">
<Image Style="{StaticResource image}" Height="22"/>
</Button>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
У кнопки есть вложенная Image, к ней подсоединен стиль:
<Style x:Key="image">
<Style.Triggers>
<DataTrigger Binding="{Binding IsState}" Value="False">
<Setter Property="Image.Source" Value="Resources/image1.png" />
</DataTrigger>
<DataTrigger Binding="{Binding IsState}" Value="True">
<Setter Property="Image.Source" Value="Resources/image2.png" />
</DataTrigger>
</Style.Triggers>
</Style>
В итоге код функционирует как и от него требовалось, а именно: кликаем на любую кнопку из списка восьми кнопок, и на кликнутой кнопке меняется картинка. Всё замечательно, за исключением, как видите, я ручками вставляю значения Canvas.Top и Canvas.Left, так как при такой компоновке кнопки не отображаются во время разработки в окне макета, а появляются только при запуске программы (это так же является минусом, от которого хочется избавиться).
Вопрос: как написать код так, чтобы у меня также на все 8 кнопок осталась одна команда, которая понимает у какой конкретно кнопки надо поменять состояние, но при этом, чтоб каждую кнопку я мог выводить в View xaml коде отдельно и менять у каждой кнопки свойства, ну как обычно, что-то типа такого:
<Button x:Name="button1" Width="41" Height="38" command="тут бинд команды" Opacity="1" Canvas.Left="100" Canvas.Top="146">
<Image Style="{StaticResource image}" Height="22"/>
</Button>
<Button x:Name="button2" Width="50" Height="12" command="тут бинд команды" Opacity="1" Canvas.Left="200" Canvas.Top="346">
<Image Style="{StaticResource image}" Height="22"/>
</Button>
и т.д., тобишь, чтоб кнопки были отображены на макете?




ItemsControl(или его аналог) и привязывайте к нужной коллекции. Вот например я делал создание кнопок в нужной ячейке, принцип тот же. – EvgeniyZ Apr 12 '20 at 11:53new Buttonподумал, что вы контрол используете, а оказывается это созданный вами класс, назвали бы хотьButtonViewModel) По поводу вопроса:не отображаются во время разработки в окне макета- задайтеd:DataContectв XAML и дизайнер начнет отображать все как надо (можете у него еще включить свойство, которое будет брать значения, заданные в конструкторе по умолчанию). ПроCanvas.Topя не понял в чем у вас проблема. Дальше,на все 8 кнопок осталась одна команда- так у вас же сейчас есть такое, нет? Вы привязываете команду и параметром передаете кнопку. – EvgeniyZ Apr 12 '20 at 12:08CommandParameter. Тут скорей всего автор хочет, чтобы в дизайнере у него во время разработки отображались данные из за этого он хочет создавать кнопки руками. Я уже вроде сказал, что для того, чтоб дизайнер отображал все необходимое, ему надо задать источник данных (DataContext, а точнееd:DataContext). Но это мое понимание вопроса, могу быть не прав... – EvgeniyZ Apr 12 '20 at 13:21как мне у кнопок менять различные свойства- Также, как вы сейчас задаетеTopиLeft?) – EvgeniyZ Apr 13 '20 at 10:03