WPF 双向绑定不适用于组合框内的复选框 [英] WPF two-way binding does not work for checkboxes inside a combobox
问题描述
我在网上尝试了很多解决方案,但我仍然遇到这个问题.我有一个组合框,其项目源是自定义类列表.源中的每个元素都显示为组合框中的复选框.现在我有一个按钮,它的 "Click"
功能是取消选中所有复选框.
I've tried lots of solutions online but I still get this issue.
I have a combobox whose item source is a list of customized class. Each element in the source is displayed as a checkbox in the combobox. Now I have a button whose "Click"
function is to uncheck all the checkboxes.
自定义类:
public class LinkObject: INotifyPropertyChanged
{
public int index { set; get; }
public string LO_Name { set; get; }
private bool _checkStatus { set; get; }
public event PropertyChangedEventHandler PropertyChanged;
public void Notify(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
public bool checkStatus
{
get { return _checkStatus; }
set
{
_checkStatus = value;
Notify("IsChecked");
}
}
}
XAML:
<ComboBox Name="cbx1" Grid.ColumnSpan="2" HorizontalAlignment="Left" Margin="126,82,0,0" VerticalAlignment="Top" Width="50" Height="20" IsEditable="True" IsTextSearchEnabled="True" StaysOpenOnEdit="True" TextBoxBase.TextChanged="cbx1_TextChanged">
<ComboBox.ItemTemplate>
<DataTemplate>
<CheckBox Name="cbk1" IsChecked="{Binding checkStatus, Mode=TwoWay}" CommandParameter="{Binding index}" Checked="chk_Checked" Unchecked="chk_Unchecked">
<CheckBox.Content>
<TextBlock Text="{Binding LO_Name}"/>
</CheckBox.Content>
</CheckBox>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
主函数初始化:
cbx1.ItemsSource = LinkObjectsList_cbx1;
LinkObjectsList_cbx1
是一个 List
.
按钮有个名字clearAllTopView",点击功能是:
The button has a name "clearAllTopView", the click function is:
private void clearAllTopViewBtn_Click(object sender, RoutedEventArgs e)
{
LinkObjectsList_cbx1.Where(l => l.checkStatus == true).ToList().ForEach(lo => lo.checkStatus = false);
}
但是当我点击按钮时,什么也没有发生.有人可以给我提示或建议吗?谢谢.
But when I click the button, nothing happens. Could someone give me a hint or advice? Thank you.
推荐答案
由于名称混淆,您遇到了一个意外错误.为了不犯这种简单但微妙的错误,我建议你使用一个简单的基类,但更好地实现INPC
.
You have an accidental error due to name confusion.
In order not to make such simple but subtle mistakes, I advise you to use a simple base class, but with a better implementation of INPC
.
这是我对这门课的版本.复制它并将其包含在您的解决方案中.
Here is my version of this class. Copy it and include it in your Solution.
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace Simplified
{
/// <summary>Base class with implementation of the <see cref="INotifyPropertyChanged"/> interface.</summary>
public abstract class BaseInpc : INotifyPropertyChanged
{
/// <inheritdoc cref="INotifyPropertyChanged"/>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>The protected method for raising the event <see cref = "PropertyChanged"/>.</summary>
/// <param name="propertyName">The name of the changed property.
/// If the value is not specified, the name of the method in which the call was made is used.</param>
protected void RaisePropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
/// <summary> Protected method for assigning a value to a field and raising
/// an event <see cref = "PropertyChanged" />. </summary>
/// <typeparam name = "T"> The type of the field and assigned value. </typeparam>
/// <param name = "propertyFiled"> Field reference. </param>
/// <param name = "newValue"> The value to assign. </param>
/// <param name = "propertyName"> The name of the changed property.
/// If no value is specified, then the name of the method
/// in which the call was made is used. </param>
/// <remarks> The method is intended for use in the property setter. <br/>
/// To check for changes,
/// used the <see cref = "object.Equals (object, object)" /> method.
/// If the assigned value is not equivalent to the field value,
/// then it is assigned to the field. <br/>
/// After the assignment, an event is created <see cref = "PropertyChanged" />
/// by calling the method <see cref = "RaisePropertyChanged (string)" />
/// passing the parameter <paramref name = "propertyName" />. <br/>
/// After the event is created,
/// the <see cref = "OnPropertyChanged (string, object, object)" />
/// method is called. </remarks>
protected void Set<T>(ref T propertyFiled, T newValue, [CallerMemberName] string propertyName = null)
{
if (!object.Equals(propertyFiled, newValue))
{
T oldValue = propertyFiled;
propertyFiled = newValue;
RaisePropertyChanged(propertyName);
OnPropertyChanged(propertyName, oldValue, newValue);
}
}
/// <summary> The protected virtual method is called after the property has been assigned a value and after the event is raised <see cref = "PropertyChanged" />. </summary>
/// <param name = "propertyName"> The name of the changed property. </param>
/// <param name = "oldValue"> The old value of the property. </param>
/// <param name = "newValue"> The new value of the property. </param>
/// <remarks> Can be overridden in derived classes to respond to property value changes. <br/>
/// It is recommended to call the base method as the first operator in the overridden method. <br/>
/// If the overridden method does not call the base class, then an unwanted change in the base class logic is possible. </remarks>
protected virtual void OnPropertyChanged(string propertyName, object oldValue, object newValue) { }
}
}
有了这个基本的实现,你的实体类就会有这样的代码:
With this basic implementation, your entity class will have code like this:
using Simplified;
namespace Febr20y
{
public class LinkObject : BaseInpc
{
public int Index { set; get; }
public string LO_Name { set; get; }
private bool _checkStatus;
public bool CheckStatus { get => _checkStatus; set => Set(ref _checkStatus, value); }
}
}
这与您的问题无关,但我建议您遵循命名指南.即,属性名称必须以大写字母开头.
This is not relevant to your question, but I advise you to follow the Naming Guidelines. Namely, property names must begin with the Upper letter.
这篇关于WPF 双向绑定不适用于组合框内的复选框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!