gpt4 book ai didi

c# - 绑定(bind)到 IEnumerable 依赖属性
转载 作者:行者123 更新时间:2023-11-30 12:24:39 24 4
gpt4 key购买 nike

我创建了一个自定义控件,名为 SearchableCheckBoxList (源自 UserControl )。在这个控件中我有一个 ItemsControl ,其中包含 Entry 类型的项目,定义如下:

public class Entry : BindableBase
{
public Entry(object content)
: this(content, false)
{ }

public Entry(object content, bool isChecked)
{
Content = content;
IsChecked = isChecked;
}

private bool _isChecked;
public bool IsChecked
{
get { return _isChecked; }
set { this.SetProperty(ref this._isChecked, value); }
}

private object _content;
public object Content
{
get { return _content; }
set { SetProperty(ref _content, value); }
}

}

在我后面的代码中,我还有一个 DependencyProperty称为 ItemsSource (属于 IEnumerable 类型),它采用(任何类型的)项目集合并将它们转换为 Entry。类型。也就是说,对于集合中的每个元素,我正在创建一个新的 Entry 项并将该元素存储在 Entry 项的 Content 属性中,如下所示:

foreach (var item in ItemsSource)
itemsControl.Items.Add(new Entry(item));

我这样做是因为在我的 ItemsControl 中我在每个项目旁边都有一个复选框,用户可以单击一个或多个复选框来选择多个项目,这将反射(reflect)在每个 Entry 的 IsChecked 属性上。元素。

我的代码后面有另一个依赖属性,叫做 SelectedItems ,定义如下:

public IEnumerable<object> SelectedItems
{
get { return (IEnumerable<object>)GetValue(SelectedItemsProperty); }
set { SetValue(SelectedItemsProperty, value); }
}
public static readonly DependencyProperty SelectedItemsProperty = DependencyProperty.Register("SelectedItems", typeof(IEnumerable<object>), typeof(SearchableCheckBoxList),
new PropertyMetadata(default(IEnumerable<object>)));

每次在我的项目控件中选中或取消选中一个项目时,我都会更新上述 DP:

private void checkBox_CheckChanged(object sender, RoutedEventArgs e)
{
var checkBox = (CheckBox)sender;

// Get entry from the content presenter
var entry = ((Entry)(((ContentPresenter)checkBox.Content).DataContext));

// Set its checked value based on the checkbox's checked value
entry.IsChecked = (bool)checkBox.IsChecked;

// Update selected items collection
SelectedItems = itemsControl.Items.Cast<Entry>().Where(i => i.IsChecked).Select(i => i.Content).ToList();

}

在我的主程序中,我是这样使用这个控件的:

<controls:SearchableCheckBoxList SelectedItems="{Binding SelectedCities, Mode=TwoWay}"
ItemsSource="{Binding CityCollection, Mode=OneTime}"/>

在我的 View 模型中 SelectedCitiesCityCollection定义如下:

private ObservableCollection<CityModel> _cityCollection;
public ObservableCollection<CityModel> CityCollection
{
get { return _cityCollection; }
set { SetProperty(ref _cityCollection, value); }
}

private List<object> _selectedCities = new List<object>();
public List<object> SelectedCities
{
get { return _selectedCities; }
set { SetProperty(ref _selectedCities, value); }
}

控件看起来像this .

现在,所有这些工作正常并且绑定(bind)正在按预期更新。我遇到的问题是,要使其正常工作,必须将 SelectedCities 定义为 List<object> .我想将 SelectedCities 定义为 List<CityModel> ,但如果我这样做,我的属性的 setter 总是以 null 值调用。我似乎无法弄清楚为什么或该做什么。

编辑 根据要求,这里是 SearchableCheckBoxList.xamlSearchableCheckBoxList.cs

最佳答案

我认为您的问题是 C# 中的集合不是协变的。我的意思是你不能投 List<Person>List<object>

class Program
{
static void Main(string[] args)
{
List<object> foo = new List<object>();
List<Person> bar = new List<Person>();

List<object> some = (List<object>) bar;
}

class Person { }
}

上面的程序无法编译。您的程序可以编译,因为强制转换是通过“SetProperty”方法间接发生的。

我认为您应该使用泛型或收集 List<IBaseClass>而不是“List<object> ”,并确保您的所有模型都继承自 IBaseClass

更新

另一种方法 - 使您的 DP 属性类型成为对象。如果有的话,这可能会让团队中的其他开发人员感到困惑。如果您的 DP 中有一些逻辑,您将必须手动检查类型并进行转换

 public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var control = new myUserControl();
myPersons = new List<Person>() { new Person() { Name = "some" } };
control.SetBinding(myUserControl.MyPropertyProperty, new Binding() { Source = MyPersons });
}

private List<Person> myPersons { get; set; }
public List<Person> MyPersons { get { return myPersons; } set { myPersons = value; } }
}

public class Person { public string Name; }

public class myUserControl : UserControl
{
public object MyProperty
{
get { return (object)GetValue(MyPropertyProperty); }
set { SetValue(MyPropertyProperty, value); }
}

// Using a DependencyProperty as the backing store for MyProperty. This enables animation, styling, binding, etc...
public static readonly DependencyProperty MyPropertyProperty =
DependencyProperty.Register("MyProperty", typeof(object), typeof(myUserControl), new PropertyMetadata(0));
}

关于c# - 绑定(bind)到 IEnumerable<object> 依赖属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33412123/

24 4 0