myCSharp.de - DIE C# und .NET Community
Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 
 | Suche | FAQ

» Hauptmenü
myCSharp.de
» Startseite
» Forum
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Suche
» Regeln
» Wie poste ich richtig?
» Forum-FAQ

Mitglieder
» Liste / Suche
» Wer ist wo online?

Ressourcen
» openbook: Visual C#
» openbook: OO
» Microsoft Docs

Team
» Kontakt
» Übersicht
» Wir über uns

» myCSharp.de Diskussionsforum
Du befindest Dich hier: Community-Index » Diskussionsforum » Entwicklung » GUI: WPF und XAML » [Gelöst] Wie kann ich ein RadioButton "IsChecked" an String Property via IValueConverter binden?
Letzter Beitrag | Erster ungelesener Beitrag Druckvorschau | Thema zu Favoriten hinzufügen

Antwort erstellen
Zum Ende der Seite springen  

[Gelöst] Wie kann ich ein RadioButton "IsChecked" an String Property via IValueConverter binden?

 
Autor
Beitrag « Vorheriges Thema | Nächstes Thema »
Kilian Kilian ist männlich
myCSharp.de-Mitglied

Dabei seit: 15.09.2019
Beiträge: 6
Entwicklungsumgebung: Visual Studio 2017 Enterprise


Kilian ist offline

[Gelöst] Wie kann ich ein RadioButton "IsChecked" an String Property via IValueConverter binden?

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo Zusammen,

wie im Titel schon erwähnt möchte ich die IsChecked Eigenschaft mittels IValueConverter an einen String binden.

Im Laufe dieses Programms kommt der User auf ein "Sub-Menü" (Window) wo er unter anderem zwei RadioButtons mit der Auswahl "JA/NEIN" findet.

Schließt der User nun das Sub-Menü und öffnet es anschließend wieder, weil er z.B. eine Eintragung vergessen hat, sollen natürlich seine bisherigen Einstellungen erhalten bleiben.

Wird zum Beispiel "JA" angeklickt, das Menü geschlossen und wieder geöffnet, springt der Konverter nachdem die IsChecked Eigenschaft auf true gesetzt wird auf "ConvertBack" mit falschen Angaben (false) und überschreibt das "X" mit "null", somit ist keiner der beiden RadioButtons selektiert.

Das Gleiche wende ich auch bei einer CheckBox an und dort funktioniert es tadellos.

Der String wird direkt nach "InitializeComponent()" an die "IsChecked" Eigenschaft gebunden.

Für eure Hilfe bedanke ich mich schon einmal im Voraus. großes Grinsen

Konverter:

C#-Code:
[ValueConversion(typeof(string), typeof(bool))]
    public class StringConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value == null) return false;
            return true;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value == null) return null;
            if ((bool)value == true) return "X";

            return null;
        }
    }

XAML:

XML-Code:
<RadioButton Content="JA"
                                    Grid.Column="1"
                                    GroupName="Point_6_1"
                                    IsChecked="{Binding Point_6_1.Yes, Mode=TwoWay, Converter={StaticResource StringConverter}}"
/>

Kilian hat dieses Bild (verkleinerte Version) angehängt:
RadioButton.png
Volle Bildgröße

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Kilian am 17.10.2020 12:43.

15.10.2020 17:21 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
witte
myCSharp.de-Mitglied

Dabei seit: 03.09.2010
Beiträge: 923


witte ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

... das müsste jemand nach WPF verschieben.
15.10.2020 18:10 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
MrSparkle MrSparkle ist männlich
myCSharp.de-Team

avatar-2159.gif


Dabei seit: 16.05.2006
Beiträge: 5.535
Herkunft: Leipzig


MrSparkle ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zeig mal den Code für die Point_6_1.Yes-Eigenschaft.

Ansonsten kannst du dir mit dem Debugger anschauen, was genau dort passiert:  [Artikel] Debugger: Wie verwende ich den von Visual Studio?

@witte: Danke für den Hinweis
@Kilian: Bitte beim nächsten Mal darauf achten, gleich im richtigen Forum zu posten. Das erhöht die Wahrscheinlichkeit auf eine korrekte Antwort :)



PS: Dieser Code:

C#-Code:
if (value == null) return false;
return true;

läßt sich auf folgende Zeile reduzieren:

C#-Code:
return (value != null);

Siehe auch  [Tipp] Anfängerhinweis == true / == false
15.10.2020 20:12 Beiträge des Benutzers | zu Buddylist hinzufügen
Kilian Kilian ist männlich
myCSharp.de-Mitglied

Dabei seit: 15.09.2019
Beiträge: 6
Entwicklungsumgebung: Visual Studio 2017 Enterprise

Themenstarter Thema begonnen von Kilian

Kilian ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Erst einmal Danke für eure Antworten smile

@witte Gibt es noch weitere Foren für WPF? GUI: WPF und XAML erschien mir das Richtige Forum zu sein. Gib mir Bescheid, damit ich beim nächsten Mal gleich im richtigen Forum posten kann.

Ich habe es mir mit dem Debugger angeschaut:

- Beim ersten öffnen des Sub-Menüs werden alle RadioButtons auf false gesetzt und im Grid.DataContext die Eigenschaft Point_6_1 hinterlegt.

- Werden nun die Einstellungen vom User getätigt und das Sub-Menü wieder geschlossen, werden alle Einstellungen gespeichert - funktioniert also.

- Wird nun das Sub-Menü wieder geöffnet und der DataContext gesetzt und die IsChecked Eigenschaft vom RadioButton auf true gesetzt wird, springt der Code direkt wieder im Converter auf die ConvertBack Methode und übergibt nicht den eben geänderten Wert true sondern false. Somit werden alle Werte wieder auf false gesetzt.

- Bei einer CheckBox, die sich auch auf dem Sub-Menü befindet funktioniert es, deshalb habe ich dieses Verhalten im Debugger angeschaut und dort springt der Code NICHT in die ConvertBack Methode und überschreibt wieder alle Werte.

Mir ist also nicht ganz klar wieso die ConvertBack Methode aufgerufen bzw ein falscher Wert "false" übergeben wird.

Das ist der Code für die Point_6_1 Eigenschaft:

C#-Code:
public class Commissioning_Points_Template_YesNo
    {
        [XmlAttribute]
        public string Yes { get; set; }

        [XmlAttribute]
        public string No { get; set; }

        public static Commissioning_Points_Template_YesNo Initialize(bool isEmpty)
        {
            Commissioning_Points_Template_YesNo init;

            init = isEmpty ? new Commissioning_Points_Template_YesNo() : new Commissioning_Points_Template_YesNo()
            {
                Yes = "X",
                No = "X"
            };

            return init;
        }
    }
17.10.2020 08:37 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
dannoe
myCSharp.de-Mitglied

Dabei seit: 24.11.2015
Beiträge: 107
Entwicklungsumgebung: VS2005-VS2017


dannoe ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top



Zitat von Kilian:
@witte Gibt es noch weitere Foren für WPF? GUI: WPF und XAML erschien mir das Richtige Forum zu sein. Gib mir Bescheid, damit ich beim nächsten Mal gleich im richtigen Forum posten kann.

Es war vorher bei "GUI: Windows-Forms" und wurde dann nach "WPF und XML" verschoben.
17.10.2020 09:58 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Kilian Kilian ist männlich
myCSharp.de-Mitglied

Dabei seit: 15.09.2019
Beiträge: 6
Entwicklungsumgebung: Visual Studio 2017 Enterprise

Themenstarter Thema begonnen von Kilian

Kilian ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Okay dann ist da etwas schief gegangen unglücklich

Ich habe mal ein kleines Programm geschrieben um die Problematik besser zu erklären/vermitteln.

Es hat zwei Windows: Hautpfenster(MainWindow) und das Sub-Menü (SubMenu). Es gibt außerdem ein Converter und ein Model in dem sich die Eigenschaften befinden.

Wie am Anfang schon gesagt werden die Einstellungen der RadioButtons nicht gespeichert bzw. beim zweiten öffnen des Sub-Menüs überschrieben.

Hauptfenster:

XML-Code:
<Window x:Class="RadioBinding.MainWindow"
        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"
        WindowStartupLocation="CenterScreen"
        mc:Ignorable="d"
        Title="RadioBinding" Height="200" Width="300"
>
    <StackPanel Margin="10">
        <Button Content="Submenu" Margin="5" Click="CmdSubMenu_Click"/>
        <Button Content="Serialize" Margin="5" Click="CmdSerialize_Click"/>
    </StackPanel>
</Window>

C#-Code:
using System.Windows;
namespace RadioBinding
{
    /// <summary>
    /// Interaktionslogik für MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public Root Root = new Root();

        public MainWindow()
        {
            InitializeComponent();

            Root = Root.Initialize(true);
        }

        private void CmdSubMenu_Click(object sender, RoutedEventArgs e)
        {
            SubMenu subMenu = new SubMenu(Root);
            subMenu.ShowDialog();
        }

        private void CmdSerialize_Click(object sender, RoutedEventArgs e)
        {
            Root.Serialize("RadioBinding.xml");
        }
    }
}

Sub-Menü

XML-Code:
<Window x:Class="RadioBinding.SubMenu"
        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:RadioBinding"
        mc:Ignorable="d"
        WindowStartupLocation="CenterScreen"
        Title="SubMenu" Height="200" Width="400"
>
    <Window.Resources>
        <local:StringConverter x:Key="StringConverter"/>
    </Window.Resources>
    <StackPanel Margin="10">
        <Grid x:Name="G_SubMenu">
            <Grid.ColumnDefinitions>
                <ColumnDefinition/>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="Auto"/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition/>
                <RowDefinition/>
                <RowDefinition/>
                <RowDefinition/>
            </Grid.RowDefinitions>

            <Grid.Resources>
                <Style TargetType="RadioButton">
                    <Setter Property="Margin" Value="3"/>
                </Style>
            </Grid.Resources>

            <TextBlock Text="Frühstück?"/>
            <RadioButton Content="JA"
                         Grid.Column="1"
                         GroupName="Breakfast"
                         IsChecked="{Binding MealCheck.Breakfast.Yes, Mode=TwoWay, Converter={StaticResource StringConverter}}"
/>
            <RadioButton Content="NEIN"
                         Grid.Column="2"
                         GroupName="Breakfast"
                         IsChecked="{Binding MealCheck.Breakfast.No, Mode=TwoWay, Converter={StaticResource StringConverter}}"
/>

            <TextBlock Text="Mittagessen?" Grid.Row="1"/>
            <RadioButton Content="JA"
                         Grid.Column="1"
                         Grid.Row="1"
                         GroupName="Lunch"
                         IsChecked="{Binding MealCheck.Lunch.Yes, Mode=TwoWay, Converter={StaticResource StringConverter}}"
/>
            <RadioButton Content="NEIN"
                         Grid.Column="2"
                         Grid.Row="1"
                         GroupName="Lunch"
                         IsChecked="{Binding MealCheck.Lunch.No, Mode=TwoWay, Converter={StaticResource StringConverter}}"
/>


            <TextBlock Text="Abendbrot?" Grid.Row="2"/>
            <RadioButton Content="JA"
                         Grid.Column="1"
                         Grid.Row="2"
                         GroupName="Dinner"
                         IsChecked="{Binding MealCheck.Dinner.Yes, Mode=TwoWay, Converter={StaticResource StringConverter}}"
/>
            <RadioButton Content="NEIN"
                         Grid.Column="2"
                         Grid.Row="2"
                         GroupName="Dinner"
                         IsChecked="{Binding MealCheck.Dinner.No, Mode=TwoWay, Converter={StaticResource StringConverter}}"
/>


            <TextBlock Text="Wurden alle Angaben korrekt angegeben?" Grid.Row="3"/>
            <CheckBox Content="Bestätigen"
                      Grid.Column="1"
                      Grid.Row="3"
                      Grid.ColumnSpan="2"
                      Margin="3"
                      IsChecked="{Binding MealCheck.IsConfirmed, Mode=TwoWay, Converter={StaticResource StringConverter}}"
/>
        </Grid>
        <Button Content="Schließen" Margin="0,5" Click="CmdClose_Click"/>
    </StackPanel>
</Window>

C#-Code:
using System.Windows;

namespace RadioBinding
{
    /// <summary>
    /// Interaktionslogik für SubMenu.xaml
    /// </summary>
    public partial class SubMenu : Window
    {
        public SubMenu(Root root)
        {
            InitializeComponent();

            G_SubMenu.DataContext = root;
        }

        private void CmdClose_Click(object sender, RoutedEventArgs e)
        {
            Close();
        }
    }
}

Converter:

C#-Code:
using System;
using System.Globalization;
using System.Windows.Data;

namespace RadioBinding
{
    [ValueConversion(typeof(string), typeof(bool))]
    public class StringConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return value != null && value.ToString() == "X";
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return value == null ? null : ((bool)value ? "X" : null);
        }
    }
}

Model:

C#-Code:
using System.IO;
using System.Xml.Serialization;

namespace RadioBinding
{

    public class Root
    {
        public Data MealCheck { get; set; }

        public Root Initialize(bool isEmpty)
        {
            return new Root()
            {
                MealCheck = Data.Initialize(isEmpty)
            };
        }

        public void Serialize(string fileName)
        {
            using (var fileStream = new FileStream(fileName, FileMode.Create))
            {
                XmlSerializer xml = new XmlSerializer(typeof(Root));
                xml.Serialize(fileStream, this);
            }
        }
    }

    public class Data
    {
        public Template Breakfast { get; set; }

        public Template Lunch { get; set; }

        public Template Dinner { get; set; }

        [XmlAttribute]
        public string IsConfirmed { get; set; }

        public static Data Initialize(bool isEmpty)
        {
            return new Data()
            {
                Breakfast = Template.Initialize(isEmpty),
                Lunch = Template.Initialize(isEmpty),
                Dinner = Template.Initialize(isEmpty),
                IsConfirmed = isEmpty ? "" : "X"
            };
        }
    }

    public class Template
    {
        [XmlAttribute]
        public string Yes { get; set; }

        [XmlAttribute]
        public string No { get; set; }

        public static Template Initialize(bool isEmpty)
        {
            return isEmpty ? new Template() : new Template() { Yes = "X", No = "X" };
        }
    }
}

Xml-Ausgabe:

XML-Code:
<?xml version="1.0"?>
<Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <MealCheck IsConfirmed="X">
    <Breakfast Yes="X" />
    <Lunch Yes="X" />
    <Dinner Yes="X" />
  </MealCheck>
</Root>
17.10.2020 11:08 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Kilian Kilian ist männlich
myCSharp.de-Mitglied

Dabei seit: 15.09.2019
Beiträge: 6
Entwicklungsumgebung: Visual Studio 2017 Enterprise

Themenstarter Thema begonnen von Kilian

Kilian ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo Zusammen,

ich habe die Lösung für mein Problem nun gefunden :)

Ich habe vergessen den DataContext vor dem schließen des Sub-Menüs auf "null" zu setzen.

Anbei die Lösung:

C#-Code:
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            G_SubMenu.DataContext = null;
        }
17.10.2020 12:40 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
MartinF
myCSharp.de-Mitglied

Dabei seit: 17.10.2020
Beiträge: 4


MartinF ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Warum bedienst du Xml nicht wie man es soll? Man verwendet Bool wenn man bool speichern will und kein string.
17.10.2020 19:34 Beiträge des Benutzers | zu Buddylist hinzufügen
MrSparkle MrSparkle ist männlich
myCSharp.de-Team

avatar-2159.gif


Dabei seit: 16.05.2006
Beiträge: 5.535
Herkunft: Leipzig


MrSparkle ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

TwoWay-DataBinding funktioniert nur dann, wenn du das PropertyChanged-Ereignis auslöst. Ansonsten solltest du das Speichern und Laden von Dateien von der Benutzeroberfläche entkoppeln, das macht es wesentlich einfacher.

Siehe dazu  [Artikel] MVVM und DataBinding und  [Artikel] Drei-Schichten-Architektur
18.10.2020 15:38 Beiträge des Benutzers | zu Buddylist hinzufügen
Baumstruktur | Brettstruktur       | Top 
myCSharp.de | Forum
Antwort erstellen


© Copyright 2003-2020 myCSharp.de-Team | Impressum | Datenschutz | Alle Rechte vorbehalten. | Dieses Portal verwendet zum korrekten Betrieb Cookies. 31.10.2020 22:49