我正在尝试检索我的 MAUI c# 桌面应用程序中“isConforme”单选按钮的值。
在我看来,该值没有正确绑定。
这是我的代码
查看:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:mct="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
xmlns:local="clr-namespace:FntrAudit.ViewModel"
x:DataType="local:NewAuditViewModel"
xmlns:model="clr-namespace:FntrAudit.Models"
x:Class="FntrAudit.Views.NewAudit"
Title="Nouvel audit" >
<HorizontalStackLayout>
<CollectionView ItemsSource="{Binding Audit.Themes}" EmptyView="pas de data">
<CollectionView.ItemTemplate >
<DataTemplate x:DataType="model:Theme">
<VerticalStackLayout Spacing="300000" >
<ImageButton
x:Name="ThemeButton"
Source="{Binding LogoTheme }"
HeightRequest="50"
Clicked="ThemeButton_Clicked"
ToolTipProperties.Text="{Binding Intitule}"
CornerRadius="100"
></ImageButton>
</VerticalStackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<CollectionView x:Name="sousthemes" ItemsSource="{Binding Audit.SousThemes}" IsVisible="false">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="model:SousTheme">
<VerticalStackLayout>
<Button Text="{Binding Intitule}"
WidthRequest="350"
Clicked="SousTheme_Clicked"
BackgroundColor="#AE1439"
></Button>
</VerticalStackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<CollectionView x:Name="question" ItemsSource="{Binding Audit.Questions}" IsVisible="false" HorizontalScrollBarVisibility="Always" VerticalScrollBarVisibility="Always">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="model:Question">
<VerticalStackLayout WidthRequest="900">
<mct:Expander x:Name="questionz" HeightRequest="220" IsExpanded="False">
<mct:Expander.Header>
<Grid BackgroundColor="LightGray" HeightRequest="100">
<Label Text="{Binding Intitule}" FontSize="16" Grid.Column="0"></Label>
<Image Source="exclamation_mark.png"
HeightRequest="20"
TranslationX="380"
ToolTipProperties.Text="{Binding RappelJuridique}"/>
</Grid>
</mct:Expander.Header>
<mct:Expander.Content>
<StackLayout
>
<HorizontalStackLayout
>
<RadioButton
x:Name="conforme"
Content="Conforme"
IsChecked="{Binding IsConforme, Mode=TwoWay}"
Value="true"
CheckedChanged="RadioButton_CheckedChanged"
>
</RadioButton>
<RadioButton
x:Name="nonConforme"
Content="Non conforme"
IsChecked="{Binding IsConforme, Mode=TwoWay}"
Value="false"
CheckedChanged="RadioButton_CheckedChanged">
</RadioButton>
<RadioButton
x:Name="nonFait"
Content="non Fait"
IsChecked="{Binding IsConforme, Mode=TwoWay}"
Value="null"
CheckedChanged="RadioButton_CheckedChanged">
</RadioButton>
</HorizontalStackLayout>
<Entry Placeholder="Commentaire" Text="{Binding Commentaire}" HeightRequest="100" ></Entry>
</StackLayout>
</mct:Expander.Content>
</mct:Expander>
</VerticalStackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<VerticalStackLayout>
<Button x:Name="record_audit"
Text="enregistrer Audit"
BackgroundColor="#AE1439"
Command="{Binding RecordAudit}">
</Button>
<Button x:Name="generate_PDF"
Text="Générer PDF"
BackgroundColor="#AE1439"
Command="{Binding GeneratePdf}">
</Button>
</VerticalStackLayout>
</HorizontalStackLayout>
</ContentPage>
隐藏代码
using CommunityToolkit.Maui.Views;
using FntrAudit.DALApi;
using FntrAudit.Models;
using FntrAudit.Services;
using FntrAudit.ViewModel;
namespace FntrAudit.Views;
public partial class NewAudit : ContentPage
{
private ISocieteUserService _societeUserService;
private IClientService _clientService;
private UserContext _userContext;
public RestService<Theme> _themeService = new RestService<Theme>();
public RestService<Audit> _themeServices = new RestService<Audit>();
public List<Theme>Themes { get; set; }
public List<SousThemeGroup> SousThemes { get; set; } = new
List<SousThemeGroup>();
public NewAudit(UserContext ContextCurrent)
{
InitializeComponent();
_userContext = ContextCurrent;
try
{
BindingContext = new NewAuditViewModel(ContextCurrent);
}
catch (Exception ex)
{
var tu = ex.Message;
}
}
private void ThemeButton_Clicked(object sender, EventArgs e)
{
question.IsVisible = false;
var imgbtn = (ImageButton)sender;
Theme btnThemeClicked = (Theme)imgbtn.BindingContext;
if (btnThemeClicked.SousThemes != null)
{
sousthemes.IsVisible = true;
sousthemes.ItemsSource = btnThemeClicked.SousThemes;
}
else
{
sousthemes.IsVisible = false;
question.IsVisible = true;
question.ItemsSource = btnThemeClicked.Questions;
}
}
private void SousTheme_Clicked(object sender, EventArgs e)
{
var btn = (Button)sender;
SousTheme btnSousThemeClicked = (SousTheme)btn.BindingContext;
// btn.BackgroundColor = Colors.LightGray;
question.IsVisible = true;
question.ItemsSource = btnSousThemeClicked.Questions;
}
private void RadioButton_CheckedChanged(object sender, CheckedChangedEventArgs e)
{
//if (sender is RadioButton radioButton && radioButton.BindingContext is Question question)
//{
// if (radioButton.IsChecked)
// {
// // Accédez à la valeur du RadioButton
// string value = radioButton.Value.ToString();
// // Mettez à jour la propriété IsConforme de l'objet Question
// question.IsConforme = bool.Parse(value);
// }
//}
if (sender is RadioButton radioButton && radioButton.BindingContext is Question question)
{
if (radioButton.Value.ToString() == "true")
{
question.IsConforme = true;
// if (e.Value)
// {
// question.IsConforme = true;
// }
}
else if (radioButton.Value.ToString() == "false")
{
question.IsConforme = false;
//if (e.Value)
//{
// question.IsConforme = false;
// }
}
else if (radioButton.Value.ToString() == "null")
{
question.IsConforme = null;
//if (e.Value)
//{
// question.IsConforme = null;
// }
}
}
}
private void record_audit_Clicked(object sender, EventArgs e)
{
var audit = e;
}
}
视图模型:
using FntrAudit.DALApi;
using FntrAudit.Models;
using FntrAudit.Services;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using CommunityToolkit.Mvvm.ComponentModel;
using FntrAudit.DocumentGenerators;
using System.Text.Json;
using Microsoft.VisualBasic;
using FntrAudit.Utils;
using FntrAudit.Data;
using Microsoft.EntityFrameworkCore;
namespace FntrAudit.ViewModel
{
public partial class NewAuditViewModel : INotifyPropertyChanged
{
private UserContext _currentContext;
private bool isSousThemeVisible;
private RestService<Theme> _themeService = new RestService<Theme>();
private RestService<Audit> _auditService = new RestService<Audit>();
private RestService<Client> _clientService = new RestService<Client>();
private Audit audit;
SqliteDbContext db = new SqliteDbContext();
private bool? isConforme;
public bool? IsConforme
{
get { return isConforme; }
set
{
if (isConforme != value)
{
isConforme = value;
OnPropertyChanged(nameof(IsConforme));
}
}
}
public bool IsSousThemesVisible
{
get => isSousThemeVisible;
set
{
SetProperty(ref isSousThemeVisible, value);
}
}
public Audit Audit
{
get => audit;
set { audit = value; OnPropertyChanged(nameof(Audit)); }
}
public List<Audit> AuditList { get; } =new List<Audit>();
public List<Theme> Themes { get; } = new List<Theme>();
public ICommand RadioButtonCommand { get; }
bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
{
if (Object.Equals(storage, value))
return false;
storage = value;
OnPropertyChanged(propertyName);
return true;
}
public NewAuditViewModel(UserContext ContextCurrent)
{
_currentContext = ContextCurrent;
if (_currentContext.IsReprise)
{
Audit = JsonSerializer.Deserialize<Audit>(_currentContext.CurrentClient.AuditEncours);
}
else
{
if (Constantes.IsBeta)
{
Audit = db.Audit
.Where(a => a.Id == 1)
.Include(a => a.Themes)
.Include(a => a.SousThemes)
.Include(a => a.Questions)
.FirstOrDefault();
}
else
{
Audit = _auditService.Get(@"https://localhost:7114/api/Audit/" + 1, new Audit());
}
}
RecordAudit = new Command(AuditRecord);
GeneratePdf = new Command(GeneratePDF);
GetSoustheme = new Command(GetSousthemes);
}
private void HandleRadioButton(string value)
{
// Logique de gestion de RadioButton ici
Console.WriteLine($"RadioButton sélectionné : {value}");
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public ICommand RecordAudit { get; set; }
public ICommand GeneratePdf { get; set; }
public ICommand GetSoustheme { get; set; }
protected virtual void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public void AuditRecord()
{
Client client = new Client();
if (Constantes.IsBeta)
{
client = db.Client.Where(c => c.Id == _currentContext.ClientId).FirstOrDefault();
}
else
{
client = _clientService.Get(@"https://localhost:7114/api/Client/" + _currentContext.ClientId, new Client());
}
var a = Audit;
client.AuditEncours = JsonSerializer.Serialize(Audit);
if (Constantes.IsBeta)
{
db.Client.Update(client);
db.SaveChanges();
}
else
{
_clientService.Create(client, @"https://localhost:7114/api/Client/updateClient", false);
}
_currentContext.CurrentClient.AuditEncours = client.AuditEncours;
}
public void GeneratePDF()
{
DocumentGenerator documentGenerator = new DocumentGenerator();
DocumentContent documentContent = new DocumentContent()
{
Audit = Audit,
Client = _currentContext.CurrentClient,
User = _currentContext.CurrentUser
};
documentGenerator.GenerateDoc(documentContent);
}
public void GetSousthemes()
{
IsSousThemesVisible = true;
}
}
}
审核模型:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FntrAudit.Models
{
public class Audit : BaseEntity, INotifyPropertyChanged
{
private string code;
private List<Theme> themes;
private List<SousTheme> sousThemes;
private List<Question> questions;
private List<QuestionLiee> questionsLiees;
public string Code
{
get { return code; }
set { code = value; OnPropertyChanged(nameof(Code)); }
}
public List<QuestionLiee> QuestionsLiees
{
get { return questionsLiees; }
set { questionsLiees = value; OnPropertyChanged(nameof(QuestionsLiees)); }
}
public List<Question> Questions
{
get { return questions; }
set { questions = value; OnPropertyChanged(nameof(Questions)); }
}
public List<SousTheme> SousThemes
{
get { return sousThemes; }
set { sousThemes = value; OnPropertyChanged(nameof(SousThemes)); }
}
public List<Theme> Themes
{
get { return themes; }
set { themes = value; OnPropertyChanged(nameof(Themes)); }
}
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged(string name) =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
问题模型:
using System.ComponentModel;
namespace FntrAudit.Models
{
public class Question: BaseEntity
{
public int ThemeId { get; set; }
public int AuditId { get; set; }
public int? SousThemeId { get; set; }
public string RappelJuridique { get; set; }
public string Code { get; set; }
public string Preconisation { get; set; }
public bool? IsConforme { get; set; }
public bool HasLinkedQuote { get; set; }
public string? Commentaire { get; set; }
//private int themeId;
//private int auditId;
//private int? sousThemeId;
//private string rappelJuridique;
//private string code;
//private string preconisation;
//private bool? isConforme;
//private bool hasLinkedQuote;
//private string commentaire;
//public int ThemeId
//{
// get { return themeId; }
// set { themeId = value; OnPropertyChanged(nameof(ThemeId)); }
//}
//public int AuditId
//{
// get { return auditId; }
// set { auditId = value; OnPropertyChanged(nameof(AuditId)); }
//}
//public int? SousThemeId
//{
// get { return sousThemeId; }
// set { sousThemeId = value; OnPropertyChanged(nameof(SousThemeId)); }
//}
//public string RappelJuridique
//{
// get { return rappelJuridique; }
// set { rappelJuridique = value; OnPropertyChanged(nameof(RappelJuridique)); }
//}
//public string Code
//{
// get { return code; }
// set { code = value; OnPropertyChanged(nameof(Code)); }
//}
//public string Preconisation
//{
// get { return preconisation; }
// set { preconisation = value; OnPropertyChanged(nameof(Preconisation)); }
//}
//public bool? IsConforme
//{
// get { return isConforme; }
// set { isConforme = value; OnPropertyChanged(nameof(IsConforme)); }
//}
//public bool HasLinkedQuote
//{
// get { return hasLinkedQuote; }
// set { hasLinkedQuote = value; OnPropertyChanged(nameof(HasLinkedQuote)); }
//}
//public string? Commentaire
//{
// get { return commentaire; }
// set { commentaire = value; OnPropertyChanged(nameof(Commentaire)); }
//}
//public event PropertyChangedEventHandler PropertyChanged;
//void OnPropertyChanged(string name) =>
// PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
我尝试了很多东西,但当我加载包含属性 isconforme 未绑定的对象审计时,没有任何效果。当我保存审计时,我有 isconforme 的良好价值,并且在我的数据库中没有问题。当我在代码中查看该属性时,该属性很好。
提前致谢
根据@Jason 评论,您不能将所有三个单选按钮绑定到同一个布尔值。另外,因为您的问题视图模型有
TwoWay
绑定,所以您不需要实现 CheckedChanged
。您将可以访问问题视图模型中的更改。
在下面,我更改了您的问题视图模型,使其具有 3 个布尔值,并且每个布尔值都会升高
PropertyChanged?
。然后,在 Audit 视图模型中,我连接到 PropertyChanged?
事件并做出相应的反应。我提供了一个模拟 MainPage.xaml
来演示 Binding
,并且所有内容都已连接,无需实现 CheckedChanged
,除了视图模型中的内容之外,我的代码隐藏中也不需要任何特殊代码。
// Question.cs ...
public class Question : INotifyPropertyChanged
{
private bool _isConforme;
public bool IsConforme
{
get { return _isConforme; }
set { _isConforme = value; OnPropertyChanged(nameof(IsConforme)); }
}
private bool _nonConforme;
public bool NonConforme
{
get { return _nonConforme; }
set { _nonConforme = value; OnPropertyChanged(nameof(NonConforme)); }
}
private bool _nonFait;
public bool NonFait
{
get { return _nonFait; }
set { _nonFait = value; OnPropertyChanged(nameof(NonFait)); }
}
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged(string name) =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
// Audit.cs ...
public class Audit : INotifyPropertyChanged
{
public IList<Question> Questions { get; } = new List<Question>();
public Audit()
{
Questions.Add(new Question());
Questions.Add(new Question());
for (int i = 0; i < Questions.Count; i++)
{
var currentQuestion = Questions[i];
currentQuestion.PropertyChanged += (s, e) => Question_PropertyChanged(i, currentQuestion);
}
}
private void Question_PropertyChanged(int index, Question currentQuestion)
{
Debug.WriteLine($"Question_PropertyChanged: {index} {currentQuestion.IsConforme} {currentQuestion.NonConforme} {currentQuestion.NonFait}");
}
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged(string name) =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
// MainPage.xaml.cs
public partial class MainPage : ContentPage
{
public Audit Audit { get; } = new Audit();
public MainPage()
{
BindingContext = this;
InitializeComponent();
}
}
<!-- MainPage.xaml ... -->
<CollectionView ItemsSource="{Binding Audit.Questions}">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="{x:Type local:Question}">
<HorizontalStackLayout>
<RadioButton Content="Conforme" IsChecked="{Binding IsConforme, Mode=TwoWay}"/>
<RadioButton Content="Non conforme" IsChecked="{Binding NonConforme, Mode=TwoWay}"/>
<RadioButton Content="non Fait" IsChecked="{Binding NonFait, Mode=TwoWay}"/>
</HorizontalStackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>