[英]Wpf ItemsControl.ItemsPanelTemplate as a Grid and add new items in different columns
我正在動態創建的網格中工作,在每個新列中都包含一個添加到ItemsControl的新項目。
我正在使用Rachel Lim的GridHelper
現在,我有一個如下的主窗口,
XAML代碼:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<local:StarsConverter x:Key="conv"/>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="9*"/>
</Grid.ColumnDefinitions>
<Button Grid.Column="0" Command="{Binding Add}"/>
<ItemsControl x:Name="list" Grid.Column="1" ItemsSource="{Binding Oc}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid x:Name="grid" Background="Black"
local:GridHelpers.StarColumns="{Binding ColumnCount, Converter={StaticResource conv}, Mode=OneWay}" local:GridHelpers.ColumnCount="{Binding ColumnCount}"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Canvas Loaded="canvas_Loaded" x:Name="canvas" Background="White">
<Border Canvas.Left="25" Canvas.Top="25" Height="25" Width="50" Background="Red">
<TextBlock Text="{Binding}"/>
</Border>
</Canvas>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</Window>
和Xaml.cs
public partial class MainWindow : Window
{
private Canvas canvas;
public MainWindow()
{
InitializeComponent();
this.DataContext = new ViewModel();
}
private void canvas_Loaded(object sender, RoutedEventArgs e)
{
ViewModel vm = this.DataContext as ViewModel;
canvas = sender as Canvas;
Binding b = new Binding();
b.Source = vm;
b.Path = new PropertyPath(ViewModel.ColumnCountProperty);
b.Mode = BindingMode.OneWay;
canvas.SetBinding(Grid.ColumnProperty, b);
}
}
此MainWindow具有一個ViewModel作為DataContext:
public class ViewModel : DependencyObject
{
private RelayCommand add;
public ViewModel()
{
}
public ObservableCollection<String> Oc
{
get { return (ObservableCollection<String>)GetValue(OcProperty); }
set { SetValue(OcProperty, value); }
}
// Using a DependencyProperty as the backing store for Oc. This enables animation, styling, binding, etc...
public static readonly DependencyProperty OcProperty =
DependencyProperty.Register("Oc", typeof(ObservableCollection<String>), typeof(ViewModel), new UIPropertyMetadata(new ObservableCollection<string>()));
public int ColumnCount
{
get { return (int)GetValue(ColumnCountProperty); }
set { SetValue(ColumnCountProperty, value); }
}
// Using a DependencyProperty as the backing store for ColumnCount. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ColumnCountProperty =
DependencyProperty.Register("ColumnCount", typeof(int), typeof(ViewModel), new UIPropertyMetadata(0));
public RelayCommand Add
{
get
{
if (this.add == null)
this.add = new RelayCommand(param => this.AddString(), param => this.CanAddString());
return this.add;
}
}
private bool CanAddString()
{
return true;
}
private void AddString()
{
this.Oc.Add("test" + ColumnCount);
ColumnCount++;
}
}
當我單擊按鈕時,命令運行良好,因此我有一個新的itemscontrol項,並且我的網格作為ItemsPanelTemplate使用新的ColumnDefinition更新,但該項不在右列中。
我知道它的答案很晚:)
一個更優雅的解決方案是在項目ViewModel中添加兩個Dependency Properties Row和Column。
然后在ItemsControl中定義一個ItemContainerStyle:
<ItemsControl>
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="Grid.Row" Value="{Binding Path=Row}" />
<Setter Property="Grid.Column" Value="{Binding Path=Column}" />
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
當您填充ItemsSource集合時,已設置“行”和“列”屬性:
for (uint i = 0; i < yourCollection.Count; ++i )
{
var item = yourCollection[i];
item.Row = (int)(i / ColumnCount);
item.Column = (int)(i % ColumnCount);
}
實際上canvas_loaded沒用...
問題來自ColumnCountChanged中的GridHelpers類。
我將其添加到SetStarColumns(grid)之后ColumnCountChanged事件的末尾,以便在相應的單元格中添加項目:
for (int i = 0; i < childCount; i++)
{
var child = grid.Children[i] as FrameworkElement;
Grid.SetColumn(child, i);
}
而且有效!
編輯:我還對ColumnCount ViewModel屬性上GridHelper.StarColumns屬性的OneWay綁定使用了一個轉換器(在上面的Xaml示例中稱為“ conv”),以使所有新創建的列具有相同的大小:
public class StarsConverter : IValueConverter
{
public object Convert(object value, Type TargetType, object parameter, CultureInfo culture)
{
int i = (int)value;
string s = "0";
for (int j = 1; j < i; j++)
{
s = s + ',' + j;
}
return s;
}
public object ConvertBack(object value, Type TargetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.