I have 2 static checkboxes:
<CheckBox x:Name="CheckOne" Content="I'm one" />
<CheckBox x:Name="CheckTwo" Content="I'm two" />
And collection of checkboxes binded to ObservableCollection:
<ItemsControl ItemsSource="{x:Bind ViewModel.CheckList, Mode=OneWay}">
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="CheckBox">
<CheckBox Content="{Binding}" IsChecked="True" IsEnabled="False" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
I need checkboxes in ItemsControl be enabled only if CheckOne is checked and CheckTwo is not checked. Is there any way to make this only using Xaml?
I tried to perform it using property in codebehind, something like:
public bool isCheckListEnabled {
get {
if ((bool)this.CheckOne.IsChecked
&& !(bool)this.CheckTwo.IsChecked)
{
return true;
}
else
{
return false;
}
}
}
And bind it to IsEnabled property of checkboxes in the ItemsControl like:
<CheckBox Content="{Binding}" IsChecked="True" IsEnabled="{x:Bind isCheckListEnabled}" />
But I have warning that "The property isCheckListEnabled was not found in type 'CheckBox'.
I assume this is because of <DataTemplate x:DataType="CheckBox">
, which means that x:
is not Page anymore but CheckBox. How to bind now anything inside of DataTemplate to Page's properties?
In a Page, this doesn't work with Window, you can add a DependencyProperty
that represents the status of the CheckBoxes. This is a working example:
MainPage.xaml
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using System.Collections.ObjectModel;
namespace App1;
public sealed partial class MainPage : Page
{
public static readonly DependencyProperty EnableCheckBoxesInItemsControlProperty =
DependencyProperty.Register(
nameof(EnableCheckBoxesInItemsControl),
typeof(bool),
typeof(MainPage),
new PropertyMetadata(default));
public MainPage()
{
this.InitializeComponent();
}
public bool EnableCheckBoxesInItemsControl
{
get => (bool)GetValue(EnableCheckBoxesInItemsControlProperty);
set => SetValue(EnableCheckBoxesInItemsControlProperty, value);
}
public ObservableCollection<string> Items { get; set; } = new()
{
"A",
"B",
"C",
};
private void CheckBox_CheckChanged(object sender, RoutedEventArgs e)
{
this.EnableCheckBoxesInItemsControl =
this.CheckBox1.IsChecked is true &&
this.CheckBox2.IsChecked is true;
}
}
MainPage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<Page
x:Class="App1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:App1"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
x:Name="ThisPage"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
mc:Ignorable="d">
<StackPanel>
<CheckBox
x:Name="CheckBox1"
Checked="CheckBox_CheckChanged"
Unchecked="CheckBox_CheckChanged" />
<CheckBox
x:Name="CheckBox2"
Checked="CheckBox_CheckChanged"
Unchecked="CheckBox_CheckChanged" />
<ItemsControl ItemsSource="{x:Bind Items, Mode=OneWay}">
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="x:String">
<CheckBox
Content="{x:Bind}"
IsEnabled="{Binding ElementName=ThisPage, Path=EnableCheckBoxesInItemsControl}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Page>
Note that I'm naming the Page
ThisPage to do the binding from inside the ItemTemplate
. This method should also work with ListView
but not with ItemsRepeater
.