Laden...

WPF ValueConverter Radio Button IsChecked doch nicht Boolean?

Erstellt von Sindelfinger vor 3 Jahren Letzter Beitrag vor 3 Jahren 831 Views
S
Sindelfinger Themenstarter:in
39 Beiträge seit 2019
vor 3 Jahren
WPF ValueConverter Radio Button IsChecked doch nicht Boolean?

Guten Morgen liebes Forum,

ich habe in meinem WPF - Fenster zwei Radio Buttons, deren Werte sich natürlich gegenseitig ausschliessen. Beim Laden des Fensters möchte ich die IsChecked - Eigenschaft natürlich von meinem Binding abhängig auf True oder False setzen.

Natürlich muss dann der andere Button dementsprechend den invertierten Wert anzeigen. Zu diesem Zweck habe ich einen Converter (geklaut):


namespace DartGames_WPF.Converters
{
    public class BoolToOppositeBoolConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter,
            System.Globalization.CultureInfo culture)
        {
            if (targetType != typeof(bool))
                throw new InvalidOperationException("The target must be a boolean");

            return !(bool)value;
        }

        public object ConvertBack(object value, Type targetType, object parameter,
            System.Globalization.CultureInfo culture)
        {
            throw new NotSupportedException();
        }
    }
}

In der Definition für das Window habe ich dann folgendes eingebaut (scheint auch richtig zu sein):


<Window x:Class="DartGames_WPF.DartGamesEinstellungen"
        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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:DartGames_WPF"
        xmlns:wpfdude="clr-namespace:DartGames_WPF.Converters"
        mc:Ignorable="d"
        Title="DartGamesEinstellungen" Height="450" Width="800" Loaded="Window_Loaded">
    <Window.Resources>
        <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
        <wpfdude:BoolToOppositeBoolConverter x:Key="oppositeConverter" />
    </Window.Resources>

Die Tatsache daß die Code - Abarbeitung in diesen Converter auch hineinspringt legt mir die Vermutung nahe, daß die Implementierung wohl korrekt ist.

Die Zeilen für die beiden Radio - Buttons und den eigentlichen Trigger:


<RadioButton  Name="rBP1Handicapped" IsChecked="{Binding  HandiCapped}" Visibility="{Binding HandicapMode, Converter={StaticResource BooleanToVisibilityConverter}}" Content="Handicap" />

<RadioButton  Name="rBP2HandiCapped" IsChecked="{Binding  HandiCapped, Converter={StaticResource oppositeConverter}}" Visibility="{Binding HandicapMode, Converter={StaticResource BooleanToVisibilityConverter}}" Content="Handicap" />

<CheckBox Name="cbHandicapMode" Grid.Column="3" Grid.Row="3" Content="Handicap Mode" IsChecked="{Binding HandicapMode}" />

(Margins und Columngedöns habe ich zur besseren Lesbarkeit hier entfernt)

Wenn also im Match (geht um Dartspiele) der Handicap - Modus nicht aktiv ist, sind diese beiden Radiobuttons nicht zu sehen - das läuft schonmal. Möchte ich aber eine Abhängigkeit des zweiten Buttons zum inversen Wert des Bindings herstellen, spuckt mir das ganze dann folgende Fehlermeldung innerhalb dieses Converters:

Fehlermeldung:
System.InvalidOperationException
HResult=0x80131509
Nachricht = The target must be a boolean
Quelle = DartGames_WPF
Stapelüberwachung:
at DartGames_WPF.Converters.BoolToOppositeBoolConverter.Convert(Object value, Type targetType, Object parameter, CultureInfo culture) in C:\Users\Rolinator\Documents\Visual Studio 2019\LerneWPF\NeuesDartGames\DartGames_WPF\BoolToOppositeBoolConverter.cs:line 16
at System.Windows.Data.BindingExpression.TransferValue(Object newValue, Boolean isASubPropertyChange)
at System.Windows.Data.BindingExpression.Activate(Object item)
at System.Windows.Data.BindingExpression.AttachToContext(AttachAttempt attempt)
at System.Windows.Data.BindingExpression.MS.Internal.Data.IDataBindEngineClient.AttachToContext(Boolean lastChance)
at MS.Internal.Data.DataBindEngine.Task.Run(Boolean lastChance)
at MS.Internal.Data.DataBindEngine.Run(Object arg)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
at System.Windows.Threading.DispatcherOperation.InvokeImpl()
at System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object state)
at MS.Internal.CulturePreservingExecutionContext.CallbackWrapper(Object obj)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)

Das wäre sicher mit Code-Behind lösbar, aber nach allem was ich über WPF gelesen habe, wäre das wohl nicht so ganz im Sinne des Erfinders. Hat da jemand eine Idee?

Vielen Dank schonmal im voraus und einen schönen Freitag gewünscht.

2 stupid 4 chess? No way.
2 stupid 4 C#? It seems so X(

4.931 Beiträge seit 2008
vor 3 Jahren

Warum schaust du dafür nicht in die Doku: ToggleButton.IsChecked (sowohl CheckBox als auch RadioButton erben von ToggleButton) ?
Der Type dafür ist also bool? (d.h. Nullable<bool>), kann also auch als dritten Status null annehmen.
Um dem Anwender alle drei Zustände zu erlauben, setze zusätzlich noch IsThreeState auf true.
Der Converter sollte aber immer mit allen drei Zuständen (true, false und null) zurechtkommen.

F
10.010 Beiträge seit 2004
vor 3 Jahren

Und eigentlich willst du das verhalten eines Radiobuttons haben.

S
Sindelfinger Themenstarter:in
39 Beiträge seit 2019
vor 3 Jahren

Und eigentlich willst du das verhalten eines Radiobuttons haben.

Völlig richtig.
Ist der gewählt Handicap - Modus auf false, soll der andere Radio - Button aktiv sein. Im weiteren Forschen habe ich herausgefunden, daß der Converter wohl den targetType anmeckert.

Den Converter habe ich mir hier abgeschaut und ihn durch einen eigenen - sehr simplen ersetzt.


using System;
using System.Globalization;
using System.Windows.Data;

namespace DartGames_WPF.Converters
{
    public class BoolInverter : IValueConverter
    {
        object IValueConverter.Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return !(bool)value;
        }

        object IValueConverter.ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return !(bool)value;
        }
    }
}

Und siehe da es geht.

@ TH69 - Ich habe natürlich in die Doku geschaut aber ich war auf einem ganz falschen Dampfer bezüglich der Fehlerursache. Unitialisierte Variablen sind in meinem Bereich der Industrieroboter ein absolutes No-Go. Und aus diesem Grund habe ich immer eine Initialisierung dabei. Ich danke Dir herzlich für Deine Antwort - die hat mir die Initialzündung gegeben.

Wie genau markiere ich das Problem jetzt als gelöst? Irgendwie finde ich da keinen Menüpunkt für.

Habt alle einen schönen Tag.

2 stupid 4 chess? No way.
2 stupid 4 C#? It seems so X(