我正在使用表单的绑定(bind)
{Binding RelativeSource={RelativeSource Self}, Path=Children.Count, Converter={StaticResource CountToDimensionConverter}, ConverterParameter=Rows}
尽管在 xaml 中添加了 child ,但当我中断转换器时,该值始终为 0。
我假设正在发生的是在调用此绑定(bind)之前不会添加子项。
我还假设绑定(bind)在被调用一次后被破坏,因为 .Count 是一个只读属性(我之前遇到过类似的问题,我不得不在属性中添加一个空的 setter 来维护绑定(bind)并愚弄 WPF)因此添加子项后绑定(bind)不会更新。
但是,我被困在您为问题提出解决方案并使其发挥作用的地方... =/
<UniformGrid x:Name="MyUniformGrid"
Rows="{Binding RelativeSource={RelativeSource Self}, Path=Children.Count, Converter={StaticResource CountToDimensionConverter}, ConverterParameter=R}"
Columns="{Binding RelativeSource={RelativeSource Self}, Path=Children.Count, Converter={StaticResource CountToDimensionConverter}, ConverterParameter=C}">
<Button Content="Hello, World!" />
<Button Content="Hello, World!" />
<Button Content="Hello, World!" />
<Button Content="Hello, World!" />
<Button Content="Hello, World!" />
<Button Content="Hello, World!" />
</UniformGrid>
谢谢,
兔子
最佳答案
这是因为 UIElementCollection
(Children
属性的类型)在添加或删除新项目时不会引发通知,因此不会刷新绑定(bind)
但是,您可以创建自己的自定义 UniformGrid
,并覆盖 CreateUIElementCollection
属性以创建继承 UIElementCollection
并实现 INotifyCollectionChanged
的自定义集合的实例。
这是一个基本的实现:
ObservableUIElementCollection
public class ObservableUIElementCollection : UIElementCollection, INotifyCollectionChanged, INotifyPropertyChanged
{
public ObservableUIElementCollection(UIElement visualParent, FrameworkElement logicalParent)
: base(visualParent, logicalParent)
{
}
public override int Add(UIElement element)
{
int index = base.Add(element);
var args = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, element, index);
OnCollectionChanged(args);
OnPropertyChanged("Count");
OnPropertyChanged("Item[]");
return index;
}
public override void Clear()
{
base.Clear();
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
OnPropertyChanged("Count");
OnPropertyChanged("Item[]");
}
public override void Insert(int index, UIElement element)
{
base.Insert(index, element);
var args = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, element, index);
OnCollectionChanged(args);
OnPropertyChanged("Count");
OnPropertyChanged("Item[]");
}
public override void Remove(UIElement element)
{
int index = IndexOf(element);
if (index >= 0)
{
RemoveAt(index);
var args = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, element, index);
OnCollectionChanged(args);
OnPropertyChanged("Count");
OnPropertyChanged("Item[]");
}
}
public override UIElement this[int index]
{
get
{
return base[index];
}
set
{
base[index] = value;
var args = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, value, index);
OnCollectionChanged(args);
OnPropertyChanged("Item[]");
}
}
public event NotifyCollectionChangedEventHandler CollectionChanged;
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
var handler = CollectionChanged;
if (handler != null)
handler(this, e);
}
protected virtual void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
MyUniformGrid
public class MyUniformGrid : UniformGrid
{
protected override UIElementCollection CreateUIElementCollection(FrameworkElement logicalParent)
{
return new ObservableUIElementCollection(this, logicalParent);
}
}
XAML
<local:MyUniformGrid x:Name="MyUniformGrid"
Rows="{Binding RelativeSource={RelativeSource Self}, Path=Children.Count, Converter={StaticResource CountToDimensionConverter}, ConverterParameter=R}"
Columns="{Binding RelativeSource={RelativeSource Self}, Path=Children.Count, Converter={StaticResource CountToDimensionConverter}, ConverterParameter=C}">
<Button Content="Hello, World!" />
<Button Content="Hello, World!" />
<Button Content="Hello, World!" />
<Button Content="Hello, World!" />
<Button Content="Hello, World!" />
<Button Content="Hello, World!" />
</local:MyUniformGrid>