Silverlight UI element's 1-time binding to nested non-dependency property fails - wpf

I want a 1-time databind between a checkbox (IsChecked propety) in a childWindow and a nested member variable in it's DataContext object, such that only the initial IsChecked property is set by the member variable. The member variable (binding source) is not INotifyPropertyChanged or marked as a DependencyProperty- but I think that is ok b/c I only want it to be evaluated once- when it gets its initial value.
Binding (in testChildWindow.xaml):
<CheckBox Content="Show Username?" Name="cbShowUser" IsChecked="{Binding Path=User.showUser}"/>
Setting DataContext (in parent window code-behind):
testChildWindow dlgBox = new testChildWindow();
dlgBox.DataContext = (this.DataContext as IAssignDlgViewModel).AssignVM("defaultChildWindow");
dlgBox.Show();
Data Context/Member variable:
public class testChildWindowViewModel : IDlgViewUpdate
{
public User
...
}
public class User
{
public bool showUser;
public User()
{
showUser = true;
}
...
}
If I make the Vm's binding source property (showUser) a dependency property at the (non-nested) testChildWindowViewModel, then the binding works. But all other combinations seem to fail.
Why must it be a dependency (or INotifyPropertyChanged?) property for a 1-time binding?
Why can't I get it to work at a nested level?
Thanks!!!

Ah, looking at the Output window during the binding answered the question for me. The problem was that User was not a property. Changed it to an auto property and the binding works just right now.

Related

Avoid Two way binding between objects in C#

When i assign a value of a class object to other class object and when i change a property of 1st object it reflects in other object.
Example:
class A has property of type int Aid
SelectedA is a property of a Viewmodel Class which is binded to A WPF View.
SelectedA.Aid is in TwoWay binding with a combo box.
i have created another object objectA and assigned objectA=SelectedA.
Problem when i change combobox value value of objectA.Aid is also changed.
Thanks in advanced i need to avoid binding of objectA with SelectedA.
Vehicle dbvalue
private Vehicle _selectedA;
public Vehicle SelectedA
{
get { return _selectedA; }
set
{
_selectedA = value;
RaisePropertyChanged("SelectedA");
}
}
public partial class A
{
public int AID { get; set; }
public string AName { get; set; }
}
<ComboBox
DisplayMemberPath="AName"
ItemsSource="{Binding items}"
SelectedValue="{Binding SelectedA.AID}"
SelectedValuePath="AName "/>
In viewmodel Class
i have used
dbvalue = SelectedA;
When i change combobox value dbvalue.AID is also changed.
You can set the behaviour of your SelectedValue binding to only update when the source changes.
SelectedValue="{Binding SelectedA.AID, Mode=OneWay}"
These are the other possible values for the Binding Mode lifted from the MSDN site:
TwoWay updates the target property or the property whenever either the target property or the source property changes.
OneWay updates the target property only when the source property changes.
OneTime updates the target property only when the application starts or when the DataContext undergoes a change.
OneWayToSource updates the source property when the target property changes.
Default causes the default Mode value of target property to be used.
Original MSDN article
To prevent of this problem, you can set it each property of object as follows:
objectA.AId = SelectedA.AId
objectA.AName = SelectedA.AName
Good Luck

Bind window model value to User Control Dependency Property

I have a simple user control that has One Dependency Property (the control is the model of itself)
The property is not directly bound to anything inside the user control, but I need to Bind its value to the Model of the window (or user control or whatever) where I put my user control.
If I set manually the User control Property Value, the property is modified correctly so I can assume the dependency property in the user control is working.
If I set the value to the Property binding it to my window model like this
<lctrl:InfoIconControl Grid.Row="0" Name="InfoIconTest" IconType="{Binding Path=IconTypeValue}"/>
Where IconTypeValue is a property of the window model, when I set the value of the window model property it does not change inside my user control. I presume I did something wrong but at the moment I have no clue.
Two possibilties come to mind as likely:
Your "model" (you mean viewmodel?) does not implement INotifyPropertyChanged and/or you're not firing the PropertyChanged when IconTypeValue changes its value.
You've done something like this.DataContext = this inside your UserControl and now the Binding is not working because it is looking for the IconTypeValue property inside your control, instead of looking for it in the "model".
Solution to option 1 is easy: implement the interface and make sure you fire the event when the property changes.
Solution to option 2 is simply removing any setting of DataContext inside your UserControl, and instead rely on relative Bindings (RelativeSource, ElementName, etc.) in your control's XAML. Or if you gotta set the DataContext of something, do NOT set the UserControl's one. Instead, set the DataContext of a container INSIDE the UserControl.
In your case, since you're using a viewmodel for your UserControl, using it as DataContext makes sense. But if you wanna support binding to the DependencyProperties of your UserControl, you're then gonna have to set your viewmodel as DataContext of something else... For instance, the first Grid in your XAML.
Just name the Grid:
<Grid x:Name="LayoutRoot">
And set your viewmodel as its DataContext:
InfoIconControlModel mModel;
public InfoIconControl()
{
InitializeComponent();
mModel = new InfoIconControlModel();
LayoutRoot.DataContext = mModel; // this.DataContext = mModel; <-- DON'T DO THIS
}
After that, the Bindings will begin to work. But you've made another typical mistake: you're only calling SetIcon from the CLR setter of your propertty.
public InfoIconType IconType
{
get
{
return (InfoIconType)this.GetValue(IconTypeProperty);
}
set
{
this.SetValue(IconTypeProperty, value);
this.SetIcon(); // <-- This won't work with Binding
}
}
Instead, you must also call it from the DependencyPropertyChanged callback (that you had already defined, on the other hand):
/// <summary>
/// Icon Type dependency Property
/// </summary>
public static readonly DependencyProperty IconTypeProperty = DependencyProperty.Register(
FLD_IconType, typeof(InfoIconType), typeof(InfoIconControl), new PropertyMetadata(InfoIconType.ICPlus, IconTypePropertyChanged));
///<summary>
///
///</summary>
private static void IconTypePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
InfoIconControl ic = sender as InfoIconControl;
ic.SetIcon(); // <-- This will work with Binding
}

Error binding a dependency property of a user control to a property on the parent's view model

I have a user control that contains three checkboxes and three date pickers. For example, one of the date pickers on the user control looks like this (irrelevant properties like Width, etc removed for clarity)...
<telerik:RadDatePicker DisplayFormat="Long"
SelectedValue="{Binding DepositPaidDate, Mode=TwoWay}"/>
The view model for the control has a public property called PaidDate that is of type PaidDate (yup, the property and the class have the same name), the top-level Grid on the control has its DataContext set to the PaidDate property, and the individual controls in the Grid are bound to properties on this PaidDate object.
When this control is used on a window, and the window's code behind sets the PaidDate property on the control's VM explicitly, it all works fine. For example, I created a test window, whose constructor looked like this...
public PaidDateWindow(PaidDate paidDate, string windowTitle) {
InitializeComponent();
((PaidDateControlViewModel)PaidDateCtrl.DataContext).PaidDate = paidDate;
Title = windowTitle;
}
...and this worked just fine. I could show the window, and the data was displayed correctly.
The problem comes when I try to set this via a dependency property on the control. The dependency property in the user control's code behind looks like this...
public static readonly DependencyProperty PaidDateProperty = DependencyProperty.Register("PaidDate", typeof(PaidDate), typeof(PaidDateControl), new FrameworkPropertyMetadata(SetPaidDateStatic));
private static void SetPaidDateStatic(DependencyObject d, DependencyPropertyChangedEventArgs e) {
(d as PaidDateControl).SetPaidDate((PaidDate)e.NewValue);
}
private void SetPaidDate(PaidDate paidDate) {
if (DataContext != null) {
((PaidDateControlViewModel)DataContext).PaidDate = paidDate;
}
}
public PaidDate PaidDate {
get {
return (PaidDate)GetValue(PaidDateProperty);
}
set {
SetValue(PaidDateProperty, value);
}
}
As you can see, the dependency property just passes the PaidDate object through to the view model, which has the same effect as when I did this manually in the previous bit of code.
When I try to bind this dependency property to a property on the window's view model, I get a binding error. Here is the XAML in the parent window...
<vrtSystemsUserControls:PaidDateControl
PaidDate="{Binding Path=VRTSystem.PaidDate, Mode=TwoWay}" />
The parent window's VM contains a property called VrtSystem, and plenty of other controls on the window are bound to properties on that. VrtSystem also contains a property called PaidDate, and that is what I want to pass to the user control.
However, when I run this, I get the following binding error...
System.Windows.Data Error: 40 : BindingExpression path error:
'VRTSystem' property not found on 'object' ''PaidDateControlViewModel' (HashCode=18319327)'.
BindingExpression:Path=VRTSystem.PaidDate; DataItem='PaidDateControlViewModel' (HashCode=18319327);
target element is 'PaidDateControl' (Name=''); target property is 'PaidDate' (type 'PaidDate')
Now it looks to me as though WPF is passing the actual binding information through to the user control, instead of the PaidDate object, as the error says it is trying to find a VrtSystem property on the user control's VM. I have no idea why it would be doing that, as I thought the idea of the binding was to resolve the binding at the window level, and then send the results (ie the PaidDate object) in to the dependency property, where it would be sent to the VM.
I hope I've explained this clearly. Anyone able to see what's gone wrong?
Thanks for any help.
When your binding is being resolved, it is looking for the VRTSystem property on the DataContext of the control it is being applied to.
The 'DataContext' property is being inherited by child-controls so if you set a DataContext on a Window all of its children will have the same DataContext. If however one of the children itself has a different DataContext applied, all of its children will use that.
In your case, the Window has a DataContext, but so has the UserControl. So by default all bindings on the UserControl or it's chilren, will expect to find the VRTSystem property on the UserControls DataContext which is not what you want in this case.
So to explicitly target the DataContext of the Window, you have to tell the binding, by setting its RelativeSource property like this:
{Binding Path=DataContext.VRTSystem.PaidDate, Mode=TwoWay,
RelativeSource={RelativeSource AncestorType={x:Type Window}}}

c# wpf Binding Command - access value of textbox from command

I want to call a simple Command which adds values from my GUI into the database.
My Command:
private ICommand addSpeechCommand;
public ICommand AddSpeechCommand
{
get
{
if (addSpeechCommand == null)
{
addSpeechCommand = new RelayCommand(param => AddSpeech());
}
return addSpeechCommand;
}
}
public void AddSpeech()
{
// TODO add
OrganizerBL.InsertSpeech(new Speech(maxSpeechId, currentSpeech.Title, currentSpeech.Summary, currentSpeech.Start, currentSpeech.End, currentSpeech.TrackId, currentSpeech.SpeakerId, currentSpeech.ConferenceId, currentSpeech.Room));
this.LoadSpeeches();
}
-- this commented out row shows how i dealt with it when a row of my datagrid was selected. but i want it to work without a currentSpeech
My XAML:
<Label x:Name ="lblTitle" Content="Title"/>
<TextBox x:Name="txtTitle" Text="{Binding CurrentSpeech.Title, Mode=TwoWay}" Margin="2,144,0,0" Height="20" VerticalAlignment="Top"/>
and other textboxes...
I really don't know how to access the values of the textboxes from the command to call my insertSpeech method...
Sorry for my english :)
UPDATE:
I'm getting a nullreference exception because my currentSpeech is null.
Is there a way to solve this without the currentSpeech?
The reason you get the NullReferenceException is probably because it's instanced in the property itself. When you cerate a binding, it's created to the property as it is at that stage. And you bind to the property when it's NULL. IT's actually created inside the property, but the Binding will never know that.
First of all, I would remove all logic from properties.
I would also implement the INotifyPropertyChanged to the class, and call the PropertyChanged in the property's "set". This means that the UI will know of any changes to the porperty.
Then I would create a depencency property for the property, if it's used in any Binding ot XAML.
Last, I would instance the command in the class's constructor.
Logic don't (in my book) belong to properties.
How to do
1. Bind TextBox.Text to View model property
2. Use View model property in Command Handler.
In your case, You have binded TextBox.Text to CurrentSpeech.Title, but using this.Title.
In you command, change this.Title to currentSpeech.Title

Expose an inner depedency property to the main user control

I am working in silverlight.
Made a new UserControl called TextBoxWithButton.
Now i want add a new property to my new control called TextBoxBackground.
I did this :
public partial class TextBoxWithButton : UserControl
{
public Brush TextBoxBackground
{
get{return textBox.Background;}
set{textBox.Background = value;}
}
}
This works fine, but when I try to animate this property I get an exception.
I think it's because TextBoxWithButton should be defined as a dependency property but I don't know exactly how to to this.
You need to turn this into a Dependency Property. For details on implementing a DP, see Custom Dependency Properties.
Once you have this setup as a Dependency Property, just bind your (inner) TextBox.Background to the "local" TextBoxBackground property (in xaml). You can then animate the UserControl's TextBoxBackground property as needed, and the "inner" property will change as well.

Resources