Data binding to a variable of an object - wpf

I'm planning to bind a textbox to a variable of an object
How am I going to do this ?
eg.
<TextBox x:Name="MaxCurrent_Tb" Margin="84,53,0,0" FontFamily="Roboto Light" Height="24" VerticalAlignment="Top" IsReadOnly="True" MaxLines="1" VerticalContentAlignment="Center" HorizontalAlignment="Left" Width="123"/>
class mainWindow(Window) :
wpf.LoadComponent(self, 'TPC_Main.xaml')
sampler = DMMSampler()
self.MaxCurrent_Tb.Text = sampler.max_current
I'm planning to bind max_current of this sampler object,
and max_current is update frequently, how do I binding this varible for real time?
I have set DataContext to another variable, so I can't set DataContext to
sampler, is there anyother way to bind to this sampler object for real time ?

Related

WPF Binding textbox to listview stops after textbox value is updated

I have a listview that when selected, will populate data from the selected lineitem into separate textboxes.
I used databinding to accomplish the task, which seems to work fine:
<TextBox x:Name="SKU_TxtBox" HorizontalAlignment="Left" Height="23" Margin="10,21,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120" Text="{Binding SelectedItem.SKU, ElementName=Inventory_ListView, Mode=OneWay}" />
The above code works correctly. The problem starts if in the codebehind I have to change the textbox value; afterwards the databinding stops.
SKU_TxtBox.text = ""
After the above line runs, the textbox will remain blank no matter what is selected in the listview.
When working with bindings, you should always manipulate only the binding source.
Inventory_ListView.SelectedItem.SKU = ""
Or a better approach is to have a View Model bound to the view. in which you define a Dependency Property (currentSKU). Then bind it to both Inventory_ListView.SelectedItem and SKU_TxtBox.text. Then it will be:
CurrentSKU = ""

wpf comboBox selectedIndex=0 is not working

.xaml
<ComboBox Grid.Row="0" Grid.Column="1" x:Name="cbx_srchResOrg" HorizontalAlignment="Stretch" Style="{DynamicResource ComboBoxStyle}"
ItemsSource="{Binding InfoCombo}" SelectedIndex="0" DisplayMemberPath="Dis_name" SelectedValuePath="Hide_id" SelectedItem="{Binding SelectInfo}"/>
Here is a part of my source code.
Why 'SelectedIndex=0' is not working?
I want to select [0] value to default at first time, but it just empty box at run time. There are no errors except it. How can I fix it?
As Hej said, you have binded the SelectedItem with a property in your view model which was null.
You can fix this by assigning the SelectedItem in your Viewmodel constructor
Public MyViewModel()
{
SelectInfo = InfoCombo[0];
}
Because you are already binding to SelectedItem. It binds two way by default, so if the property binded to it(SelectInfo) is null, it will also be set to null.
You can also use Mode=OneWayToSource in the SelectedItem binding with SelectedIndex="0".
In your case:
<ComboBox Grid.Row="0"
Grid.Column="1"
x:Name="cbx_srchResOrg"
HorizontalAlignment="Stretch"
Style="{DynamicResource ComboBoxStyle}"
ItemsSource="{Binding InfoCombo}"
SelectedIndex="0"
DisplayMemberPath="Dis_name"
SelectedValuePath="Hide_id"
SelectedItem="{Binding SelectInfo, Mode=OneWayToSource}"/>
Like others said, it binds two way by default, so if the property binded to it (SelectInfo) is null, it will also be set to null.
you have bind SelectedItem to SelectInfo, you should set value(in your viewmodel) to SelectInfo as default, for example
SelectInfo = InfoCombo[0] or something other whatevere you want to set as default value

How to keep bindings when serializing a WPF usercontrol into an XElement

I'm trying to serialize a custom WPF user control that features a grid with a textblock that is bound to a dependency property named "Frequency". The snippet that defines the textblock is as follows (the definition of the user control is quite lengthy to post it here!):
<TextBlock x:Name="FrequencyText" Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2"
FontFamily="Arial Rounded MT"
Foreground="White" FontSize="10" FontWeight="DemiBold" Margin="3"
TextBlock.Text="{Binding Frequency, ElementName=FrequencyButtonControlA, Path=Frequency}"
TextAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Left" />
I'm working on an editor tool that enables the user to arrange some custom controls into a canvas and change their properties and I need to provide the user with the capability to clone an existing element. In order to do this, I'm serializing the control into an XElement and instantiating a new one afterwards. The code to perform the serialization is as follows:
var contentXaml = (commsPanelItem.Content != null) ? XamlWriter.Save(commsPanelItem.Content) : string.Empty;
var serializedItem = new XElement(
"CommsPanelItem",
new XElement("Type", commsPanelItem.GetType().ToString()),
new XElement("Left", Canvas.GetLeft(commsPanelItem.UIElement)),
new XElement("Top", Canvas.GetTop(commsPanelItem.UIElement)),
new XElement("Width", commsPanelItem.Width),
new XElement("Height", commsPanelItem.Height),
new XElement("zIndex", Panel.GetZIndex(commsPanelItem.UIElement)),
new XElement("Content", contentXaml),
commsPanelItem.GetAttributesForSavingPanelInConfigurator() as XElement);
return serializedItem;
The problem I'm having is that, when serializing the textblock, the "Text" field doesn't preserve the binding to the "Frequency" dependency property, it just gets exported with the value assigned by the user ("131.5" in the following example):
TextBlock Text="131.5" FontFamily="Arial Rounded MT" FontWeight="SemiBold" FontSize="10" Foreground="#FFFFFFFF" TextAlignment="Center" Name="FrequencyText" Margin="3,3,3,3" HorizontalAlignment="Left" VerticalAlignment="Center" Grid.Column="1" Grid.Row="1" Grid.ColumnSpan="2"
My question is: is there any way to be able to serialize dependency property's binding instead of the actual value?
Thanks in advance!
Use the "GetBinding" method found on FrameworkElements instead of pulling its value:
BindingExpression bindingExpression = myTextBox.GetBindingExpression(TextBox.TextProperty);
Then you can probably serialize the BindingExpression.

Is it possible to bind to a lambda expression in Silverlight?

I have a listbox that simply binds to a collection. The collection has a child collection (StepDatas). I would like to bind to a count of the child collection but with a WHERE statement. I can bind to ChildCollection.Count but get lost when needing to add the lambda expression. Here's the XAML:
<ListBox Height="Auto" Style="{StaticResource ListBoxStyle1}" Margin="4,46,4,4" x:Name="lstLeftNavigation" Background="{x:Null}" SelectionChanged="lstLeftNavigation_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Width="180" Margin="2,2,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" d:LayoutOverrides="Width" MinHeight="36">
<TextBlock Text="{Binding StepNm}" x:Name="tbStepNm" Margin="10,0,34,0" TextWrapping="Wrap" FontFamily="Portable User Interface" Foreground="White" FontSize="10" FontWeight="Bold" VerticalAlignment="Center"/>
<Image Height="37" HorizontalAlignment="Right" Margin="0" VerticalAlignment="Center" Width="37" Source="Images/imgIcoChecked.png" Stretch="Fill"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
The above works to bind to the count of the child collection. However I wish to show a count of the child collection where a certain condition is met. In this specific case, the child collection has a completed property (bool). So...I want to show the count StepDatas.Where(x => x.Completed == true).Count.
Is this in any way possible? Thanks for any help!
The short answer to the subject question is: no.
The sensible answer is: Ensure the Count you need is made available a property of the data model. E.g., ensure the type exposed by StepDatas has a Count property.
However you do qualify this with "in any way possible?". It is possible to bind to the ListItem data context and using some value converter madness to execute your lambda. However to keep things simple you need to create a converter specifically for your lambda.
Here is what the converter code would look like:-
public class CountCompletedStepDatas : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
YourItemsType item = (YourItemsType)value;
return item.StepDatas.Were(x => x.Completed == true).Count().ToString(culture);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
You would the make an instance of this converter avaiable in a Resources property in the XAML, say of convenience in the UserControl:-
<UserControl x:Class="YourNameSpace.ThisControlName"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:YourNameSpace;assembly=YourAssemblyName">
<UserControl.Resources>
<local:CountCompletedStepDatas x:Key="Counter" />
</UserContro.Resources>
Now in your binding:-
<TextBlock Text="{Binding Converter={StaticResource Counter} }" ... >
Thanks for the response. After submitting the question, I wrote a converter class to do what you ended up suggesting but discovered that the count property will not cause a rebind when the data changes. This will force a situation where we will have to manually update the binding when changes are made. Getting a reference of the image object inside the listbox in order to update the target is unforntunately a pain in the arse!
Ultimately, I just added a new field to the datasource and bound the image directly to it like you suggested. Much cleaner.
Thanks for the suggestions!
Doug

Silverlight Label content binding problems

I'll preface this and say that I'm new to Silverlight development by about week so I'm most likely doing it wrong...
Anyway I have a Label and a TextBox done up thusly in XAML:
<dataInput:Label Target="{Binding ElementName=JobCode}" Height="18" HorizontalAlignment="Left" Margin="15,7,0,0" Name="lableJobCode" VerticalAlignment="Top" Width="250" FontWeight="Bold" Grid.Column="1" />
<TextBox Height="23" Text="{Binding SelectedRole.Job_Code}" HorizontalAlignment="Left" Margin="15,31,0,0" Name="JobCode" VerticalAlignment="Top" Width="277" Grid.Column="1" IsReadOnly="{Binding IsNotAdmin}" />
Everything works great, the only issue I have is that the binding I'm doing on the IsReadOnly attribute which goes to a boolean in my ViewModel which is set based on a call to an authentication service, is now overriding the label Content to the name of my ViewModel property: IsNotAdmin. I can't seem to find a way to specify which data binding source to pull the label content MetaData from. Maybe I'm missing something on how to manipulate control editablity/visibility from my ViewModel.
--Update: The data source class that the TextBox is bound to is as follows (for the relevant parts):
public class RoleSummary {
[Display(Name= "Job Code (To be Completed by HR):")]
public string Job_Code { get; set; }
Without the binding to the IsReadOnly attribute the Label displays the text from the data annotation just fine. When I add the binding it displays "IsNotAdmin"
can you post more of your code? I'm not entirely sure what it is that you're trying to make happen so it's hard to propose a solution.
I assume you're trying to create a text entry element that has validation performed on it (hence the label) -- but what exactly is the label supposed to be showing for it's content?
EDIT: I figured this out. The label control by default looks through all the properties in its datacontext looking for metadata it can use. For whatever reason it decided to use the metadata for the IsNotAdmin property in your code (even though you didn't set it manually, I assume that the Display metadata gets a default value of the property name), and so you get that for the text of the label.
Microsoft put in a property specifier into the data controls so you can tell it which property it should use for the metadata lookup: PropertyPath
Try it like this:
<dataInput:Label Target="{Binding ElementName=JobCode}" PropertyPath="SelectedRole.Job_Code" Height="18" HorizontalAlignment="Left" Margin="15,7,0,0" Name="lableJobCode" VerticalAlignment="Top" Width="250" FontWeight="Bold" Grid.Column="1" />
<TextBox Height="23" Text="{Binding SelectedRole.Job_Code}" HorizontalAlignment="Left" Margin="15,31,0,0" Name="JobCode" VerticalAlignment="Top" Width="277" Grid.Column="1" IsReadOnly="{Binding IsNotAdmin}" />
As long as your datacontext is right (which it should be) this should work for you -- it worked in my sample I reconstructed from your code.

Resources