Добрый день. Внезапно понадобился листбокс, но не простой, а с доп свойствами, хотелось бы, чтобы он имел примерно такую структуру:
То есть я хочу сделать листбокс, в котором будет список объектов, у которых будет какой-то текст, картинки и тд и чтобы это все отображалось в одной строке. Какими способами можно это сделать? Желательно не сильно муторными. Спасибо
Простой пример на WPF с биндингами коих в инете полно.
XAML:
<Window.DataContext>
<local:ListBoxViewModel />
</Window.DataContext>
<ListBox ItemsSource="{Binding Items}" x:Name="ListBox">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Width="50" Source="{Binding ImageSource}" />
<TextBlock Width="200" Text="{Binding Text}" />
<Button Content="Удалить"
CommandParameter="{Binding}"
Command="{Binding ElementName=ListBox, Path=DataContext.DeleteCommand}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
ViewModel и Model:
public class ListBoxItemModel
{
public ListBoxItemModel(string imageSource, string text)
{
ImageSource = imageSource;
Text = text;
}
public string ImageSource { get; }
public string Text { get; }
}
public class ListBoxViewModel
{
public ListBoxViewModel()
{
Items = new ObservableCollection<ListBoxItemModel>
{
new ListBoxItemModel("http://www.playground.ru/img/ui/playground-main-logo-new.png", "someText1"),
new ListBoxItemModel("http://www.playground.ru/img/ui/playground-main-logo-new.png", "someText2")
};
DeleteCommand = new Prism.Commands.DelegateCommand<ListBoxItemModel>
(item => this.Items.Remove(item));
}
public ObservableCollection<ListBoxItemModel> Items { get; }
public ICommand DeleteCommand { get; }
}
Не очень красиво и на скорую руку, но вполне рабочий пример. Итак, сперва нужно создать некоторые вспомогательные классы для реализации MVVM
паттерна - без него сам не хожу в WPF и вам не советую, так что не пугайтесь - часть всей этой простыни из разряда - один раз вставил и забыл. Так же можно использовать какой-либо MVVM
-фреймворк - где все это (И даже больше) есть, но я считаю, что для начала лучше в рукопашную...
"База" для ViewModel
- ViewModelBase.cs
:
public class ViewModelBase : INotifyPropertyChanged
{
protected void OnPropertyChanged(PropertyChangedEventArgs e)
{
var handler = PropertyChanged;
handler?.Invoke(this, e);
}
protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
Два класса команд (с параметром и без - целиком стащил с какого-то сайта побыстрому):
public class RelayCommand<T> : ICommand
{
#region Fields
readonly Action<T> _execute;
readonly Predicate<T> _canExecute;
#endregion // Fields
#region Constructors
public RelayCommand(Action<T> execute)
: this(execute, null)
{
}
public RelayCommand(Action<T> execute, Predicate<T> canExecute)
{
_execute = execute ?? throw new ArgumentNullException(nameof(execute));
_canExecute = canExecute;
}
#endregion // Constructors
#region ICommand Members
[DebuggerStepThrough]
public bool CanExecute(object parameter)
{
return _canExecute?.Invoke((T)parameter) ?? true;
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter)
{
_execute((T)parameter);
}
#endregion // ICommand Members
}
public class RelayCommand : ICommand
{
#region Fields
readonly Action<object> _execute;
readonly Predicate<object> _canExecute;
#endregion // Fields
#region Constructors
public RelayCommand(Action<object> execute)
: this(execute, null)
{
}
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
#endregion // Constructors
#region ICommand Members
[DebuggerStepThrough]
public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter)
{
_execute(parameter);
}
#endregion // ICommand Members
}
Приступаем. Нам нужно окно где всё отображать. Запихиваем в MainWindow.xaml
примерно такой xaml
-код:
<Window
x:Class="WPFApplication1.Views.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"
Title="{Binding Title}"
d:DesignHeight="388.602"
d:DesignWidth="485.968"
ResizeMode="CanResize"
mc:Ignorable="d">
<Grid x:Name="LayoutRoot">
<ListView
Grid.ColumnSpan="3"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch"
ItemsSource="{Binding ElementList}"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListView.ItemTemplate>
<DataTemplate>
<Grid HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Image
Grid.Column="0"
Height="60"
Source="{Binding ImageUri}" />
<TextBlock
Grid.Column="1"
HorizontalAlignment="Stretch"
Text="{Binding Title}" />
<StackPanel Grid.Column="2" Orientation="Horizontal">
<Button Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type ListView}}, Path=DataContext.RemoveCommand}" CommandParameter="{Binding}">Удалить</Button>
<Button Command="{Binding SelectCommand}">Выбрать</Button>
</StackPanel>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
К нему прилагается вью модель:
public class MainViewModel : ViewModelBase
{
private string _title;
public string Title
{
get { return _title; }
set { _title = value;
OnPropertyChanged();
}
}
public ObservableCollection<Element> ElementList { get; set; }
public MainViewModel()
{
ElementList = new ObservableCollection<Element>();
}
private RelayCommand<Element> _removeCommand;
public RelayCommand<Element> RemoveCommand => _removeCommand ??
(_removeCommand = new RelayCommand<Element>(element =>
{
ElementList.Remove(element);
}));
}
Далее нужна вьюмодель для элементов списка:
public class Element : ViewModelBase
{
private string _title;
private Uri _imageUri;
public string Title
{
get { return _title; }
set
{
_title = value;
OnPropertyChanged();
}
}
private RelayCommand _selectCommand;
public RelayCommand SelectCommand => _selectCommand ??
(_selectCommand = new RelayCommand(obj =>
{
MessageBox.Show(Title, "Вы выбрали");
}));
public Uri ImageUri
{
get { return _imageUri; }
set
{
_imageUri = value;
OnPropertyChanged();
}
}
public Element(string title)
{
Title = title;
}
}
Далее нам нужно все это связать. Идем в App.xaml.cs
и прописываем в OnStartap
:
protected override void OnStartup(StartupEventArgs e)
{
var mainVm = new MainViewModel {Title = "Главное окно"};
mainVm.ElementList.Add( new Element("1") {ImageUri =new Uri(@"http://steshka.ru/wp-content/uploads/2015/03/cifra_1_2.jpg") });
mainVm.ElementList.Add(new Element("два") { ImageUri = new Uri(@"http://www.raskraska.ru/zifra_digital/img/dva_yellow.gif") });
mainVm.ElementList.Add(new Element("Третий элемент") { ImageUri = new Uri(@"http://izgotovlenie-trafaretov.ru/wp-content/uploads/2014/11/trafaret-cifra-3-tip1.jpg") });
var mw = new MainWindow {DataContext = mainVm};
mw.Show();
base.OnStartup(e);
}
В принципе если я ничего не забыл - все должно заработать.
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Я только начал разбираться с RequireJS, но у меня появился уже вопросДопустим я имею два плагина для jQuery: a
Для того чтобы снова ввести число, нужно обновить страничкуМожно ли сделать, чтобы после неверного ответа программа сама снова предлагала...
В Уроках Javascript с нуляУрок 6 - Циклы утверждается, что этот цикл устаревший (между 13 и 15 минутами)