Преобразование содержимого сетки в ListView или другое для использования в шаблоне MVVM
У меня есть 5 X 4 Grid (код ниже), который работает так, как нужно для формы моих данных. Недавно я обнаружил, что практически невозможно передать сетку из модели представления в представление и связать ее с другой сеткой в XAML, и при этом поддерживать шаблон MVVM - что является моей целью.
Проблема в том, что моя презентация требует, чтобы дочерние элементы были сгруппированы в отдельные ячейки, каждая из которых имеет 1 изображение и два элемента пользовательского интерфейса с текстовым блоком.
Кажется, что DataTable, DataSet, GridView, List и т. Д. Не имеют возможности добавлять несколько дочерних элементов в отдельные ячейки строк / столбцов для отображения. К сожалению, это не просто вставка изображения в заголовок столбца.
Кто-нибудь нашел другой вариант сделать подобное?
Спасибо,
Гленн
Ниже приведен пример сетки и изображение результирующего вида.
public void FormatGridCell()
{
Random random = new Random();
List<int> randomNumList = new List<int>();
for (int i = 0; i < 50; i++)
randomNumList.Add(random.Next(50));
List<string> columHeader = new List<string>();
columHeader.Add("Pitts");
columHeader.Add("Vans");
columHeader.Add("Lancair");
columHeader.Add("Epic");
List<string> rowHeader = new List<string>();
rowHeader.Add("NORTH");
rowHeader.Add("SOUTH");
rowHeader.Add("EAST");
rowHeader.Add("WEST");
rowHeader.Add("CANADA");
for (int x = 1; x < 5; x++)
{
var engineType= new TextBlock { Text = columHeader[x - 1] };
engineType.SetValue(Grid.RowProperty, 0);
engineType.SetValue(Grid.ColumnProperty, x);
engineType.HorizontalAlignment = HorizontalAlignment.Center;
this.airplaneGrid.Children.Add(engineType);
for (int r = 1; r < 6; r++)
{
var dealerService = new TextBlock { Text = rowHeader[r - 1] };
dealerService.SetValue(Grid.RowProperty, r);
dealerService.SetValue(Grid.ColumnProperty, 0);
dealerService.HorizontalAlignment = HorizontalAlignment.Center;
this.airplaneGrid.Children.Add(dealerService);
for (int i = 1; i < 6; i++)
{
// Bitmap path will be based on Type
var modelImage = new Image { Width = 20, Height = 20 };
var bitmapImage = new BitmapImage(new Uri(@"c:\personal\temp\dog.jpg"));
modelImage.Source = bitmapImage;
modelImage.SetValue(Grid.RowProperty, r);
modelImage.SetValue(Grid.ColumnProperty, i);
modelImage.HorizontalAlignment = HorizontalAlignment.Left;
modelImage.VerticalAlignment = VerticalAlignment.Top;
var mfgName = new TextBlock { Text = "Lancair IV" };
mfgName.SetValue(Grid.RowProperty, r);
mfgName.SetValue(Grid.ColumnProperty, i);
mfgName.HorizontalAlignment = HorizontalAlignment.Center;
var price = new TextBlock { Text = "$" + randomNumList[r + i] };
price.SetValue(Grid.RowProperty, r);
price.SetValue(Grid.ColumnProperty, i);
price.HorizontalAlignment = HorizontalAlignment.Left;
price.VerticalAlignment = VerticalAlignment.Center;
price.Margin = new Thickness(30, 0, 0, 0);
this.airplaneGrid.Children.Add(modelImage);
this.airplaneGrid.Children.Add(mfgName);
this.airplaneGrid.Children.Add(price);
}
}
}
}
Эта функция не моя. Извините, забыл названный кредит, но этот парень из стека overoverflow предоставил этому форуму.
public static class RandomExtensions
{
public static int NextDouble(
Random random,
double minValue,
double maxValue)
{
return random.Next(10, 50);
}
}
Извините, я слишком низко на тотемном столбе, чтобы отправить изображение, но запустите его для полного понимания предполагаемого расположения.
Вот XAML для поддержки вышеизложенного.
<Grid x:Name="airplaneGrid" ShowGridLines="True">
<Grid.RowDefinitions>
<RowDefinition Height="60" />
<RowDefinition Height="60"/>
<RowDefinition Height="60"/>
<RowDefinition Height="60"/>
<RowDefinition Height="60"/>
<RowDefinition Height="60"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="175"/>
<ColumnDefinition Width="175"/>
<ColumnDefinition Width="175"/>
<ColumnDefinition Width="175"/>
<ColumnDefinition Width="175"/>
</Grid.ColumnDefinitions>
</Grid>
2 ответа
Вы можете использовать другую сетку (или панель стека, или любой другой тип панели) в качестве дочернего элемента в каждой ячейке, а затем добавить дочерние элементы на эту панель.
Хорошо. Я поместил ваше решение и мое из стороны в сторону. Это выглядит так:
По общему признанию, это требует немного больше настройки, но вы поймете основную идею.
<ListView ItemsSource="{Binding}" Grid.Column="1">
<ListView.Resources>
<DataTemplate x:Key="CellContentTemplate">
<Border BorderBrush="LightGray" BorderThickness="1">
<DockPanel>
<Image Height="20" Width="20" Source="{Binding ImageSource}" Margin="2"
DockPanel.Dock="Left"/>
<StackPanel>
<TextBlock Text="{Binding Value, StringFormat='${0}'}" Margin="2"/>
<TextBlock Text="{Binding Name}" Margin="2"/>
</StackPanel>
</DockPanel>
</Border>
</DataTemplate>
</ListView.Resources>
<ListView.View>
<GridView>
<GridViewColumn Header="" DisplayMemberBinding="{Binding Name}"/>
<GridViewColumn Header="Pitts">
<GridViewColumn.CellTemplate>
<DataTemplate>
<ContentPresenter Content="{Binding Pitts}" ContentTemplate="{StaticResource CellContentTemplate}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Vans">
<GridViewColumn.CellTemplate>
<DataTemplate>
<ContentPresenter Content="{Binding Vans}" ContentTemplate="{StaticResource CellContentTemplate}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Lancair">
<GridViewColumn.CellTemplate>
<DataTemplate>
<ContentPresenter Content="{Binding Lancair}" ContentTemplate="{StaticResource CellContentTemplate}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Epic">
<GridViewColumn.CellTemplate>
<DataTemplate>
<ContentPresenter Content="{Binding Epic}" ContentTemplate="{StaticResource CellContentTemplate}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
Код сзади (просто случайные данные):
Random random = new Random();
public GridSample() //Window Constructor
{
InitializeComponent();
var names = new[] {"NORTH","SOUTH","EAST","WEST"};
DataContext = names.Select(x => new GridViewModel()
{
Name = x,
Epic = CreateRandomCell(),
Lancair = CreateRandomCell(),
Pitts = CreateRandomCell(),
Vans = CreateRandomCell()
});
}
private CellViewModel CreateRandomCell()
{
return new CellViewModel
{
Name = "Cell" + random.Next(0, 100),
ImageSource = "/ChessPieces/BlackBishop.png",
Value = (decimal) random.Next(0, 100)
};
}
ViewModels:
public class GridViewModel
{
public string Name { get; set; }
public CellViewModel Pitts { get; set; }
public CellViewModel Vans { get; set; }
public CellViewModel Lancair { get; set; }
public CellViewModel Epic { get; set; }
}
public class CellViewModel
{
public string Name { get; set; }
public string ImageSource { get; set; }
public decimal Value { get; set; }
}
Увидеть? чистый MVVM, чистое, красивое решение.