Xaml mvvm中的3状态复选框绑定,无法设置空状态
我正在使用MVVM创建一个UWP应用程序。在我的xaml视图中,我有一个3状态复选框。我的复选框在一个列表视图中,这个列表视图也有一个子列表视图,有更多的复选框,所以本质上是嵌套的复选框列表。如果选中了内部listview中的任何复选框,我将尝试使外部listview中的复选框处于空状态。如果选择了所有内部复选框,我希望外部复选框处于true状态,如果未选择任何复选框,我希望它处于false状态。我正在使用委托命令来实现这些事件处理程序 我能够成功地使正确和错误案例工作,但是我无法使复选框在UI上显示状态null,因为它在我的ViewModel中的值成功地更改为nullXaml mvvm中的3状态复选框绑定,无法设置空状态,xaml,checkbox,mvvm,data-binding,uwp,Xaml,Checkbox,Mvvm,Data Binding,Uwp,我正在使用MVVM创建一个UWP应用程序。在我的xaml视图中,我有一个3状态复选框。我的复选框在一个列表视图中,这个列表视图也有一个子列表视图,有更多的复选框,所以本质上是嵌套的复选框列表。如果选中了内部listview中的任何复选框,我将尝试使外部listview中的复选框处于空状态。如果选择了所有内部复选框,我希望外部复选框处于true状态,如果未选择任何复选框,我希望它处于false状态。我正在使用委托命令来实现这些事件处理程序 我能够成功地使正确和错误案例工作,但是我无法使复选框在UI
<ListView ItemsSource="{Binding ObxList, Mode=TwoWay}">
<ListView.ItemTemplate>
<DataTemplate>
<CheckBox IsChecked="{x:Bind IsSelected, Mode=TwoWay}" IsThreeState="True" Command="{Binding DataContext.ClickCommand, ElementName=Y}">
<TextBlock Text="{x:Bind Value}" />
</CheckBox>
<ListView ItemsSource="{Binding Children}" Visibility="{Binding visibility, Mode=TwoWay}">
<ListView.ItemTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsSelected, Mode=TwoWay}"
IsThreeState="False" Command="{Binding DataContext.ChildCommand, ElementName=Y}">
<TextBlock Text="{Binding Value}"/>
</CheckBox>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</DataTemplate>
</ListView.ItemTemplate>
</ListView
{
返回t.Children.Count()==0;
}))
{
如果(item.IsSelected==true)
{
var parent=item.GetParent(AllObjectsList);
if(parent.IsSelected==null | | parent.IsSelected==false)
{
//检查是否选择了所有子项
//并将父项更改为true(如果是)
//如果仅选择了一些,则为null
bool allChildrenSelected=true;
foreach(parent.GetChildren中的var child(AllObjectsList))
{
if(child.IsSelected==false)
{
allChildrenSelected=false;
打破
}
}
如果(已选择所有儿童)
{
parent.IsSelected=true;
}
其他的
{
parent.IsSelected=new Nullable();
}
}
}
else if(item.IsSelected==false)
{
var parent=item.GetParent(AllObjectsList);
if(parent.IsSelected==null)
{
//检查是否所有子项都未选中
//如果是,则将父项设置为false
//如果不是,则将父项设置为null
bool noChildrenSelected=true;
foreach(parent.GetChildren中的var child(AllObjectsList))
{
if(child.IsSelected==true)
{
noChildrenSelected=false;
打破
}
}
如果(未选择儿童)
{
parent.IsSelected=false;
}
}
else if(parent.IsSelected==true)
{
parent.IsSelected=null;
}
}
}
}
这是因为WinRT不支持绑定到可空类型
@Jerry Nixon-MSFT有三种方法解决这个问题,他的博客中提供了一些示例。这是因为WinRT不支持绑定到可空类型
@Jerry Nixon-MSFT有三种方法解决这个问题,他的博客中提供了一些示例。这是因为WinRT不支持绑定到可空类型
@Jerry Nixon-MSFT有三种方法解决这个问题,他的博客中提供了一些示例。这是因为WinRT不支持绑定到可空类型
@Jerry Nixon-MSFT有三种方法来解决这个问题,他的博客中提供了一些示例。最终的问题是
依赖性属性的实现复选框。IsChecked
。WinRT中不隐式支持可空基元类型绑定,在WinRT中,基础类型是IReference1
,这是一个内部定义,因此我们无法使用简单类型转换器来解决此问题
技术上是正确的,@Jerry Nixon在中提供了一些有用的背景信息,但它只表明存在解决方法,而不是具体如何实现它们
这篇文章中的建议在近10年的UWP中仍然有用:。最简单的解决方法是创建一个新的依赖项属性,该属性类型为对象
这是许多第三方控件库中的常见解决方案,通常可以找到对象
类型化的值
属性和单独类型化的属性
这可以通过附加属性来实现,但是我更喜欢扩展复选框
类:
//
///复选框控件,支持不确定状态的绑定
///
/// https://www.danrigby.com/2012/07/24/windows-8-dev-tip-nullable-dependency-properties-and-binding/
公共类BindableCheckBox:复选框
{
公共BindableCheckBox()
{
this.isthrestate=true;
//从可为空的状态开始!
this.IsChecked=null;
//连接UI事件以手动适当设置值
this.Checked+=BindableCheckBox\u Checked;
this.Unchecked+=BindableCheckBox\u Unchecked;
this.undeterminate+=BindableCheckBox\u undeterminate;
//连接属性已更改事件,以防某个笨蛋以其他方式设置ISCHECK
this.RegisterPropertyChangedCallback(CheckBox.IsCheckedProperty,(s,e)=>
{
如果(s是可绑定复选框cb)
{
如果(!cb.\U值正在更改)
{
public void ChildCheckboxHandler()
{
// gets all of the lowest level children
foreach (Object item in AllObjectsList.Where(t =>
{
return t.Children.Count() == 0;
}))
{
if (item.IsSelected == true)
{
var parent = item.GetParent(AllObjectsList);
if (parent.IsSelected == null || parent.IsSelected == false)
{
// checks if all children are selected
// and changes the parent to true if so
// null if only some are selected
bool allChildrenSelected = true;
foreach (var child in parent.GetChildren(AllObjectsList))
{
if (child.IsSelected == false)
{
allChildrenSelected = false;
break;
}
}
if (allChildrenSelected)
{
parent.IsSelected = true;
}
else
{
parent.IsSelected = new Nullable<Boolean>();
}
}
}
else if (item.IsSelected == false)
{
var parent = item.GetParent(AllObjectsList);
if (parent.IsSelected == null)
{
// checks if all the children are unchecked
// if they are, then sets the parent to false
// if they are not, then sets the parent to null
bool noChildrenSelected = true;
foreach (var child in parent.GetChildren(AllObjectsList))
{
if (child.IsSelected == true)
{
noChildrenSelected = false;
break;
}
}
if (noChildrenSelected)
{
parent.IsSelected = false;
}
}
else if (parent.IsSelected == true)
{
parent.IsSelected = null;
}
}
}
}