Binding an Nicht-Steuerelement-Property möglich?
-
Hi,
mit "normalen" Bindings an Steuerelemente komme ich gut zurecht. Nun brauche ich ein Binding zur Property einer eigenen Klasse. Beim googeln findet man aber immer nur Beispiele wie man an Steuerelemente bindet.
Binding b = new Binding("Property_of_mySourceObject"); b.Source = sourceObject; BindingOperations.SetBinding(myTargetObject, ??? ,b);
Was muss ich denn bei "???" reinschreiben damit das klappt?
Grüsse
-
Hi,
hier mal ein Minimalbeispiel:
<Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <Grid> <TextBox Name="testBox" /> </Grid> </Window>
Hier wird das Binding direkt auf die Textbox gesetzt mit dem Pfad zur TestProperty.
public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); DataContext = new ViewModel(); testBox.SetBinding(TextBox.TextProperty, "TestProperty"); } }
Der übliche OnPropertyChanged Kram, damit die View auch mitbekommt wenn du im Code die TestProperty änderst.
public class ViewModel : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); } public string _testProperty; public string TestProperty { get { return _testProperty; } set { if (_testProperty != value) { _testProperty = value; OnPropertyChanged("TestProperty"); } } } }
mfG
KaPtainCugel
-
@KaPtainCugel
zwar danke für das ausführliche Beispiel (ein paar Kleinigkeiten kann man immer dazu lernen) aber mein Problem liegt woanders, weil ich ja nicht an ein Steuer-Element binden will.
public class Class1 { public int Class1_Property { get; set; } } public class Class2 { public int Class2_Property { get; set; } }
MainWindow:
Class1 class1 = new Class1(); Class2 class2 = new Class2(); Binding b = new Binding("Class1_Property"); b.Source = class1; class2.SetBinding(class2.Class2_Property, b);
Da bekomme ich eine Fehlermeldung dass "SetBinding" nicht definiert ist.
-
Hi,
das hatte ich falsch verstanden. Was du vor hast geht meines Wissens nach so nicht. SetBinding ist in der Klasse Control definiert, wenn du also nicht von Control ableitest, dann hast du es auch nicht zur Verfügung. Was genau ist denn das Ziel was du erreichen möchtest?
-
Hm, ok, geht also so nicht. Trotzdem danke.
Was ich machen will ist, dass eine int Property, die z.B. 0,1,2 sein kann, drei "Lämpchen" bzw. Ellipsen ansteuert. Bei "0" soll z.B. ein vorher dunkelgrünes Lämpchen hellgrün werden usw.
Ich muss also mit 6 Farbtönen arbeiten. Das könnte ich zwar in meiner Klasse machen, ich will aber Objekt-Verweise und static weitgehend vermeiden bzw. die Kommunikation nach aussen möglichst nur über Bindings realisieren.
Das geht natürlich irgendwie über ein Binding aber damit bin ich noch überfordert, und Beispiele im Netz sind fast alle XAML, mit dem ich mich schwer tue bzw. ich versuch immer alles mit Code zu realisieren.Gibt's eigentlich ein Tool, das XAML-Code in C#-Code übersetzt?
-
So ein Tool ist mir nicht bekannt, ich kann dir eigentlich nur raten XAML zu lernen, weil damit viele Sachen wesentlich einfacher und kompakter werden.
Vom grundsätzlichen Vorgehen bei dieser Sache würde ich dir empfehlen, dass du dir einen Converter schreibst, der das Ganze für dich erledigt.
Hier mal ein kleines Beispiel wie es mit Hilfe von XAML aussehen könnte, den C# Code bekommst du dann sicher hin:MainWindow:
<Window.Resources> <wpfApplication1:IntToColorConverter x:Key="IntToColorConverter" /> </Window.Resources> <StackPanel Orientation="Horizontal" VerticalAlignment="Top"> <Ellipse Fill="{Binding State, Converter={StaticResource IntToColorConverter}}" Width="30" Height="30"/> <Ellipse Fill="{Binding State, Converter={StaticResource IntToColorConverter},ConverterParameter=1}" Width="30" Height="30"/> <Ellipse Fill="{Binding State, Converter={StaticResource IntToColorConverter},ConverterParameter=2}" Width="30" Height="30"/> </StackPanel>
public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); ViewModel model = new ViewModel(); DataContext = model; DispatcherTimer timer = new DispatcherTimer(new TimeSpan(0,0,1), DispatcherPriority.Background, (sender, args) => model.State++, Dispatcher); timer.Start(); } }
Das ViewModel:
public class ViewModel : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); } private int _state; public int State { get { return _state; } set { if (_state != value) { _state = value; OnPropertyChanged("State"); } } } }
Der Converter:
public class IntToColorConverter : IValueConverter { readonly List<Brush> _colors = new List<Brush>(){Brushes.Green, Brushes.Yellow, Brushes.Red}; public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { int state = (int) value; int offset = parameter == null ? 0 : Int32.Parse(parameter.ToString()); return _colors[(state + offset)%_colors.Count]; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } }
Vielleicht hilft dir das ja ein wenig bei deiner Problemstellung weiter und zeigt dir eine mögliche Lösung, ansonsten frag ruhig nochmal wenn du etwas noch genauer wissen möchtest.
-
@KPC
Erstmal wieder vielen Dank an Dich, war mir eine grosse Hilfe und hab's jetzt auch.Ich habe es vereinfacht so weit wie es ging und für alle, die auch wissen wollen wie man das nur mit C#-Code macht,
stelle ich mein Beispiel hier ein (Drei Ellipsen und drei Buttons auf's Formular ziehen und Code kopieren).Die Steuer-Eigenschaft-Klasse:
public class C_Ampel : INotifyPropertyChanged { // Events public event PropertyChangedEventHandler PropertyChanged; // Private variables private int status; // Contructor public C_Ampel() { status = 0; } // Properties public int Status { get { return status; } set { status = value; OnPropertyChanged("Status"); } } protected virtual void OnPropertyChanged(string property) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(property)); } } }
Die Konverter-Klasse:
public class IntToColorConverter : IValueConverter { // Private Variables int triggerValue; Brush brushOn; Brush brushOff; // Constructor public IntToColorConverter(int triggerValue_Init, Brush brushOn_Init, Brush brushOff_Init) { triggerValue = triggerValue_Init; brushOn = brushOn_Init; brushOff = brushOff_Init; } // Properties // Methods public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { Brush ReturnColor = brushOff; if ((int)value == triggerValue) { ReturnColor = brushOn; } return ReturnColor; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } }
Und MainWindow:
public partial class MainWindow : Window { C_Ampel Ampel = new C_Ampel(); public MainWindow() { InitializeComponent(); } private void Window_Loaded(object sender, RoutedEventArgs e) { // Green Binding GreenBinding = new Binding("Status"); GreenBinding.Converter = new IntToColorConverter(0, Brushes.Lime, Brushes.Green); GreenBinding.Source = Ampel; ellipse1.SetBinding(Ellipse.FillProperty, GreenBinding); // Yellow Binding YellowBinding = new Binding("Status"); YellowBinding.Converter = new IntToColorConverter(1, Brushes.Yellow, Brushes.Goldenrod); YellowBinding.Source = Ampel; ellipse2.SetBinding(Ellipse.FillProperty, YellowBinding); // Red Binding RedBinding = new Binding("Status"); RedBinding.Converter = new IntToColorConverter(2, Brushes.Red, Brushes.DarkRed); RedBinding.Source = Ampel; ellipse3.SetBinding(Ellipse.FillProperty, RedBinding); } private void button1_Click(object sender, RoutedEventArgs e) { Ampel.Status = 0; } private void button2_Click(object sender, RoutedEventArgs e) { Ampel.Status = 1; } private void button3_Click(object sender, RoutedEventArgs e) { Ampel.Status = 2; } }
Grüsse