Мне нужно иметь возможность отображать списки данных в ListBox с кнопками, которые могут перемещать элементы вверх и вниз и удалять элементы из ListBoxes и отражать это в моделях данных.
SampleDesign: http://bigriverrubber.com/_uploads/sites/2/usercontrollistbox.jpg
Я планирую иметь несколько списков ListBox, подобных этой, с одинаковыми функциями в нескольких окнах, поэтому я подумал, что мог бы создать UserControl со списком ListBox и нужными мне кнопками внутри, чтобы кнопки изменяли данные.Таким образом, я мог бы просто передать ObservableCollection в UserControl, и мне не пришлось бы каждый раз заново создавать кнопки.
Однако я обнаружил, что не могу перемещать элементы, если они связаныв коллекцию ObservableCollection, которой они должны быть для моих целей.Из того, что я прочитал, мне нужно вместо этого изменить коллекцию.
Но как мне это сделать из UserControl?Если тип ObservableCollection должен быть переменным, чтобы ListBox мог отображать множество типов списков, как я могу надеяться на него, чтобы получить доступ к методам Move и Remove в классе ObservableCollection?
I 'мы пытались взять ItemsSource, который был установлен в ObservableCollection, и преобразовать его в ObservableCollection , но это не сработало.
Я попытался привести его к типу ObservableCollection и ObservableCollection среди прочего, безрезультатно.
Я даже пытался реструктурировать мои ViewModel под GenericViewModel со свойством ObservableCollection , что привело к ошибке и оставило мой код в руинах, поэтому мне пришлось вернуться к резервной копии.
Я использовал ItemsControl, который изменяет ListBox в зависимости от того, какой тип DataType он находит, но это все равно будет означать, что я все равно должен делать отдельные события кнопки, так какой смысл?
Я бы опубликовалнекоторый код, но, видя, как ничего я не сделал, я работалЯ ни малейшего сомневаюсь, что это поможет любому.На данный момент я даже не знаю, можно ли вообще сделать то, что я собираюсь сделать.
Если есть какие-либо предложения по поводу того, какой код размещать, не стесняйтесь спрашивать.РЕДАКТИРОВАТЬ: Вот GenericViewModel.Это не работает, потому что я не знаю, на что установить «Все».РЕДАКТИРОВАТЬ: Добавлено UserControl
public class GenericViewModel : Observable
{
//-Fields
private ObservableCollection<Anything> _items;
private Anything _selectedItem;
//-Properties
public ObservableCollection<Anything> Items
{
get { return _items; }
set { Set(ref _items, nameof(Items), value); }
}
public Anything SelectedItem
{
get { return _selectedItem; }
set { Set(ref _selectedItem, nameof(SelectedItem), value); }
}
//-Constructors
public GenericViewModel()
{
if (Items == null) Items = new ObservableCollection<Anything>();
}
//-Logic
public void MoveUp()
{
if (Items == null) return;
Helper.MoveItemUp(Items, _items.IndexOf(_selectedItem));
}
public void MoveDown()
{
if (Items == null) return;
Helper.MoveItemDown(Items, _items.IndexOf(_selectedItem));
}
public void Remove()
{
if (Items == null) return;
Helper.RemoveItem(Items, _items.IndexOf(_selectedItem));
}
}
UserControl
public partial class CustomListBox : UserControl
{
//-Fields
//-Properties
//-Dependencies
//-Constructor
public CustomListBox()
{
InitializeComponent();
}
//-Methods
private void ListboxButtonUp_Click(object sender, RoutedEventArgs e)
{
}
private void ListboxButtonDown_Click(object sender, RoutedEventArgs e)
{
}
private void ListboxButtonCopy_Click(object sender, RoutedEventArgs e)
{
}
private void ListboxButtonDelete_Click(object sender, RoutedEventArgs e)
{
}
private void BorderLayerThumbnail_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
}
private void BorderLayerThumbnail_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
}
}
<UserControl x:Class="BRRG_Scrubber.User_Controls.CustomListBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:BRRG_Scrubber"
mc:Ignorable="d"
d:DesignHeight="200" d:DesignWidth="150">
<Grid Grid.Row="0" Margin="5,0,0,0">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<TextBlock Text="{Binding Name}" Grid.Row="0" FontSize="10" Foreground="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
<!--ItemsSource="{Binding Items}" SelectedItem="{Binding Current}"-->
<ListBox x:Name="listBoxPlus" Grid.Row="1" ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem}" >
<ListBox.Resources>
<Style x:Key="{x:Type ScrollBar}" TargetType="{x:Type ScrollBar}">
<Setter Property="Stylus.IsFlicksEnabled" Value="True" />
<Style.Triggers>
<Trigger Property="Orientation" Value="Vertical">
<Setter Property="Width" Value="14" />
<Setter Property="MinWidth" Value="14" />
</Trigger>
</Style.Triggers>
</Style>
<DataTemplate DataType="{x:Type local:Document}">
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
<DataTemplate DataType="{x:Type local:Variable}">
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
<DataTemplate DataType="{x:Type local:Layer}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.30*" />
<ColumnDefinition Width="0.70*" />
</Grid.ColumnDefinitions>
<Border x:Name="borderLayerThumbnail" BorderBrush="#FF707070" BorderThickness="1" Width="50" Height="50" MouseRightButtonDown="BorderLayerThumbnail_MouseRightButtonDown" MouseLeftButtonDown="BorderLayerThumbnail_MouseLeftButtonDown" >
<Border.Background>
<ImageBrush ImageSource="/BRRG_Scrubber;component/Resources/Images/checkerboardtile.jpg" ViewportUnits="Absolute" Stretch="None" Viewport="0,0,12,12" TileMode="Tile"/>
</Border.Background>
<Image Grid.Column="0" Source="{Binding Image}" Stretch="Uniform" HorizontalAlignment="Center" VerticalAlignment="Center" OpacityMask="Gray">
<Image.Style>
<Style TargetType="Image">
<Setter Property="Opacity" Value="1.0"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Visible}" Value="False">
<Setter Property="Opacity" Value="0.5"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</Border>
<StackPanel Grid.Column="1" VerticalAlignment="Center" Margin="10,0,0,0">
<TextBox Text="{Binding Name}"/>
<TextBlock Text="{Binding Type, Mode=OneWay}"/>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
<TextBlock Text="?" FontSize="12">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Opacity" Value="1.0"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Visible}" Value="False">
<Setter Property="Opacity" Value="0.2"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<TextBlock Text="?" FontSize="12">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Opacity" Value="1.0"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Locked}" Value="False">
<Setter Property="Opacity" Value="0.2"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</StackPanel>
</StackPanel>
</Grid>
</DataTemplate>
</ListBox.Resources>
</ListBox>
<WrapPanel Grid.Row="2" HorizontalAlignment="Right">
<WrapPanel.Resources>
<Style TargetType="Button">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" />
<Setter Property="Background" Value="{x:Null}" />
<Setter Property="FontSize" Value="10" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Width" Value="20" />
<Setter Property="Height" Value="20" />
</Style>
</WrapPanel.Resources>
<Button x:Name="listboxButtonUp" Content="▲" Click="ListboxButtonUp_Click"/>
<Button x:Name="listboxButtonDown" Content="▼" Click="ListboxButtonDown_Click"/>
<Button x:Name="listboxButtonCopy" Content="⧉" Click="ListboxButtonCopy_Click"/>
<Button x:Name="listboxButtonDelete" Content="⛞" Click="ListboxButtonDelete_Click"/>
</WrapPanel>
</Grid>
</UserControl>
Я действительно хотел бы иметь возможность создавать модифицированный ListBox в UserControl с кнопками, которые могут перемещать элементы вверх иВниз и удалите их из списка, который я могу использовать для любой ObservableCollection любого неизвестного типа.Все нужные мне ListBox будут функционировать одинаково, за исключением того, что их Тип будет неизвестен до времени выполнения.
РЕДАКТИРОВАТЬ: Новый код из предложений Эда
MainViewModel
public class MainViewModel : Observable
{
//-Fields
private Project _project;
private GenericViewModel<Document> _documentCollection;
private GenericViewModel<Variable> _variableCollection;
private GenericViewModel<Layer> _layerCollection;
//-Properties
public Project Project
{
get { return _project; }
set { Set(ref _project, nameof(Project), value); }
}
public GenericViewModel<Document> DocumentCollection
{
get { return _documentCollection; }
set { Set(ref _documentCollection, nameof(DocumentCollection), value); OnPropertyChanged(nameof(LayerCollection)); }
}
public GenericViewModel<Variable> VariableCollection
{
get { return _variableCollection; }
set { Set(ref _variableCollection, nameof(VariableCollection), value); }
}
public GenericViewModel<Layer> LayerCollection
{
get { return _layerCollection; }
set { Set(ref _layerCollection, nameof(LayerCollection), value); }
}
//-Constructors
public MainViewModel()
{
Project = new Project();
DocumentCollection = new GenericViewModel<Document>();
DocumentCollection.Items = Project.Documents;
}
//-Logic
}
Тестовое окнос привязками
<StackPanel>
<uc:CustomListBox DataContext="{Binding DocumentCollection}" Height="100"/>
<uc:CustomListBox DataContext="{Binding LayerCollection}" Height="200"/>
<ListBox ItemsSource="{Binding Project.Documents}" Height="100"/>
</StackPanel>
GenericViewModel
public class GenericViewModel<Anything> : Observable, ICollectionViewModel
{
//-Fields
private ObservableCollection<Anything> _items;
private Anything _selectedItem;
//-Properties
public ObservableCollection<Anything> Items
{
get { return _items; }
set { Set(ref _items, nameof(Items), value); }
}
public Anything SelectedItem
{
get { return _selectedItem; }
set { Set(ref _selectedItem, nameof(SelectedItem), value); }
}
//-Constructors
public GenericViewModel()
{
if (Items == null) Items = new ObservableCollection<Anything>();
}
//-Logic
...Removed For Brevity...
}
Класс модели документа
public class Document : Anything
{
//-Fields
private string _filePath = "New Document";
private ObservableCollection<Layer> _layers;
private ObservableCollection<Selection> _selections;
//-Properties
public string FilePath
{
get { return _filePath; }
set { Set(ref _filePath, nameof(FilePath), value); }
}
public ObservableCollection<Layer> Layers
{
get { return _layers; }
set { Set(ref _layers, nameof(Layers), value); }
}
//-Constructors
public Document()
{
if (Layers == null) Layers = new ObservableCollection<Layer>();
if (Selections == null) Selections = new ObservableCollection<Selection>();
}
public Document(string filepath)
{
this.FilePath = filepath;
if (Layers == null) Layers = new ObservableCollection<Layer>();
if (Selections == null) Selections = new ObservableCollection<Selection>();
Layers.Add(new Layer("LayerOne "+Name));
Layers.Add(new Layer("LayerTwo " + Name));
Layers.Add(new Layer("LayerThree " + Name));
Selections.Add(new Selection());
Selections.Add(new Selection());
}
//-Gets
public string Name
{
get { return Path.GetFileNameWithoutExtension(FilePath); }
}
}