| 

.NET C# Java Javascript Exception

2
Hallo,

ich habe ein Usercontrol geschrieben, welches eine LED darstellen soll.
Wenn ich aber die gebundene Property auf true schalten (LED ein) dann schaltet die
LED nicht ein.

Der PropertyChanged Mechanismus funktioniert: Wenn ich die gleiche Property mit einer Checkbox binde, wird die Checkbox markiert, sobald ich mit dem Button die Property für LED ein auf true setze.

Komischerweise funktioniert die LED, wenn ich die LED mit mit der Checkbox (IsChecked) verbinde.

Der Fehler muss in der Implementierung des Usercontrols liegen. Wenn ich anstatt der LED eine Checkbox verwende, dann schaltet die Checkbox richtig um (Checked/Unchecked).


  • DataContext ist gesetzt
  • PropertyChanged Interface ist vorhanden




Usercontrol LED (XAML):

<UserControl x:Class="LedTest.MyLed"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

mc:Ignorable="d"
d:DesignHeight="80" d:DesignWidth="82" >
<UserControl.Resources>

</UserControl.Resources>
<Grid >
<Border Effect="{Binding LedEffect}">
<Rectangle RadiusX="5" RadiusY="5" Fill="{Binding LedColor,FallbackValue=Gold}" />
</Border>
</Grid>
</UserControl>




UserControl LED Codebehind:

/// <summary>
/// Interaction logic for MyLed.xaml
/// </summary>
public partial class MyLed : UserControl, INotifyPropertyChanged
{
#region Felder
private SolidColorBrush _ledColor;
private DropShadowEffect _ledEffect;
#endregion

#region Properties
public DropShadowEffect LedEffect
{
get { return _ledEffect; }
set { _ledEffect = value; RaisePropertyChanged("LedEffect"); }
}

public SolidColorBrush LedColor
{
get { return _ledColor; }
set { _ledColor = value;

RaisePropertyChanged("LedColor");
}
}

#endregion

#region Dependency Properties
public static readonly DependencyProperty HiColorProperty =
DependencyProperty.Register("HiColor", typeof(SolidColorBrush), typeof(MyLed), new PropertyMetadata(Brushes.LawnGreen));

public SolidColorBrush HiColor
{
get { return (SolidColorBrush) GetValue(HiColorProperty); }
set { SetValue(HiColorProperty, value); }
}


public static readonly DependencyProperty LoColorProperty =
DependencyProperty.Register("LoColor", typeof(SolidColorBrush), typeof(MyLed), new PropertyMetadata(Brushes.Lavender));

public SolidColorBrush LoColor
{
get { return (SolidColorBrush)GetValue(LoColorProperty); }
set { SetValue(LoColorProperty, value); }
}
public static readonly DependencyProperty OnProperty =
DependencyProperty.Register("On", typeof(bool), typeof(MyLed), new PropertyMetadata( false, CallbackOnOff));

public bool On
{
get { return (bool)GetValue(OnProperty); }
set
{
SetValue(OnProperty, value);
RaisePropertyChanged("On");
}
}

/// <summary>
/// Callback für Dep. Property "On"
/// </summary>
/// <param name="d"></param>
/// <param name="e"></param>
private static void CallbackOnOff(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var control = d as MyLed;
if (control != null)
{
var newValue = e.NewValue is bool && (bool)e.NewValue;

if (newValue) //LED ist an
{
control.LedColor = control.HiColor;
control.LedEffect = new DropShadowEffect { BlurRadius = control.ActualWidth / 2, ShadowDepth = control.ActualWidth / 10 };
}
else //LED ist aus
{
control.LedColor = control.LoColor;
control.LedEffect = null;// new DropShadowEffect { BlurRadius = 0, ShadowDepth = 0 };
}
}
}


#endregion


/// <summary>
/// Kontruktor
/// </summary>
public MyLed()
{
InitializeComponent();
DataContext = this;
_ledColor = LoColor;
if (On)
LedEffect = new DropShadowEffect { BlurRadius = ActualWidth / 2, ShadowDepth = ActualWidth / 10 };
}


/// <summary>
/// Interface
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void RaisePropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}




Das ist mein MainWindow (XAML):
<Window x:Class="LedTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:ledTest="clr-namespace:LedTest"
Title="MainWindow" Height="350" Width="525" >
<Grid >
<StackPanel>
<!--hier funktioniert die LED nicht:-->
<StackPanel Orientation="Horizontal">
<Label Content="LED gebunden mit der Property 'LedAn' (funktioniert nicht) :"></Label>
<ledTest:MyLed Height="16" Width="16" On="{Binding LedIsOn}" />
</StackPanel>

<!--Test mit Checkbox funktioniert-->
<StackPanel Orientation="Horizontal">
<Label Content="Checkbox gebunden mit der Property 'LedAn' (funktioniert):"></Label>
<CheckBox x:Name="checkbox" IsChecked="{Binding LedIsOn}" />
</StackPanel>

<!--LED mit Checkbox verbunden funktioniert:-->
<StackPanel Orientation="Horizontal">
<Label Content="LED gebunden mit Checkbox IsChecked (Elementbinding): (funktioniert)"></Label>
<ledTest:MyLed Height="16" Width="16" On="{Binding ElementName=checkbox, Path=IsChecked}" />
</StackPanel>


<Label Margin="0 32 0 0" Content="Warum geht die 1. LED nicht? Die gleiche Property wurde verwendet,"/>
<Label Content="die auch bei der Checkbox verwendet wurde."/>

<Button Content="LED on" Width="60" Margin="16" Click="ButtonLedAn"/>
<Button Content="LED off" Width="60" Margin="16" Click="ButtonLedAus"/>
</StackPanel>

</Grid>
</Window>


Das ist der Code-Behind zum Main-Window:
public partial class MainWindow : Window, INotifyPropertyChanged
{
private bool _ledIsOn;
public bool LedIsOn
{
get { return _ledIsOn; }
set { _ledIsOn = value; RaisePropertyChanged("LedIsOn"); }
}


public MainWindow()
{
InitializeComponent();
DataContext = this;
}

/// <summary>
/// LED einschalten
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ButtonLedAn(object sender, RoutedEventArgs e)
{
LedIsOn = true;
}

/// <summary>
/// LED ausschalten
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ButtonLedAus(object sender, RoutedEventArgs e)
{
LedIsOn = false;
}

/// <summary>
/// Interface für INotifyPropertyChanged
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void RaisePropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
News:
11.02.2013
mattdotnet 23 3
2 Antworten
1
Dadurch, dass Du im Control selbst den DataContext auf this festlegst, zeigt Dein Binding
<ledTest:MyLed Height="16" Width="16" On="{Binding LedIsOn}" />
für die On-Property auf MyLed.LedIsOn. Diese Property existiert aber nicht, deshalb tut sich auch nichts mit Deinem Led.

Wenn Du Dein Binding so änderst, funktionierts.
<ledTest:MyLed Height="16" Width="16" On="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=LedIsOn}" />

Ich würde das Design des Controls nochmal überdenken, damit Du ohne solche Umwege auskommst.
11.02.2013
ffordermaier 8,4k 3 9
0
Hallo,

vielen Dank für die Antwort. Jetzt ist mir das klar.

Ich habe die XAML so geändert und das setzen des DataContext im CodeBehind entfernt:

<UserControl x:Class="LedTest.MyLed"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
x:Name="myled"
mc:Ignorable="d"
d:DesignHeight="80" d:DesignWidth="82" >
<Grid>
<Border Effect="{Binding ElementName=myled, Path=LedEffect}">
<Rectangle RadiusX="5" RadiusY="5" Fill="{Binding ElementName=myled, Path=LedColor}" />
</Border>
</Grid>
</UserControl>
11.02.2013
mattdotnet 23 3
So ists deutlich besser.
ffordermaier 11.02.2013

Stelle deine Databinding-Frage jetzt!