TextBlock Text Binding an ObservableCollection.Count property - wpf

I have a ObservableCollection<Sportisti> that starts out with 0 elements (but is initialized to a new object at the creation of the window). I wanted to bind the Count property to a TextBox. Unfortunately, this causes my application to crash whenever I try to open the window in question.
Now, since I have a ListView on the same page, successfully showing the elements of the collection in question, I thought I could simply extract the number of rows from there, but that also lead to a crash.
<TextBox Text="{Binding ElementName=lvTabela, Path=Items.Count}"
Grid.Row="4" Grid.Column="1" Margin="0,3,60,3"
DockPanel.Dock="Top" IsReadOnly="True" />
Note that in the .xaml file I can see the content of the TextBox is 0.
Any idea why this is happening?

My mistake, I forgot to add the Mode=OneWay to the binding. The problem was that, even though the TextBox wasn't editable, the system recognized this as a potential way of changing the ListView.ItemCount attribute, which is read-only.

My suggestion: Initialize your collection to empty objects in your code when the the list initializes.
This may help you.

Related

ComboBox has extra space at the bottom

I have a ComboBox that shows empty space below its values. See picture below.
The data in the view model is set in a button click handler. When I set the values in the initialization of the view model the ComboBox is fine. When I try to create a small example the ComboBox also has the expected size. It seems it depends somehow on the context where I set the values in the view model but I cannot figure out. I hope someone can give me a hint.
Code in the view model
Repositories.Clear();
Repositories.Add("One");
Repositories.Add("Two");
Repositories.Add("Three");
SelectedRepository = "One";
Code in XMAL
<ComboBox MinWidth="150"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
IsEnabled="{Binding CT.Connected}"
ItemsSource="{Binding CT.Repositories,
UpdateSourceTrigger=PropertyChanged}"
SelectedItem="{Binding CT.SelectedRepository}"/>
The ItemsSource you are binding to needs to be an ObservableCollection. The ComboBox will display the initial blank space if you bind the ItemsSource to any enumerable type that doesn't raise property changed when its items change.
When I try to create a small example the ComboBox has the expected size.
By that logic it maybe not the combobox, but the data which is in the list. Can you verify that there are not 8 items where the textual value to display is empty for the last four items or so?
Or
Maybe a style is causing the extra space. Try removing the style from the combobox such as this
<ComboBox Style="{x:Null}"/>
and see if it has any effect to the visual result.
Or
Also how about not setting the data and see if the drop down has the same size?

How does WPF handle binding to the property of a null object?

I have a listBox using an itemTemplate that contains the following line:
<Image Source="{Binding MyProperty.PossiblyNullObject.UrlProperty}"/>
Bound to this listBox is a model view collection that loads components of the items in the collection on a separate thread. The 'PossiblyNullObject' may not be set to a value when the xaml code is first rendered by the composition engine.
How does WPF handle this? Does it use a default value(no image source so no image) and continue on? Does it wait? Does it automatically detect when the value is initialized and rerenders with the new source? How does it not throw object null exceptions in the same way it would if I called 'MyProperty.PossiblyNullObject.UrlProperty' programmatically? How can I reproduce this functionality in my own code when I try to call it?
Thanks for any suggestions. I am embarrassingly new to WPF and I'm trying to tackle a problem out of my depth. The image load is a perf problem so I found a solution to load, decode, then freeze the image source on a background thread so it wouldn't lock up the UI. Unfortunately, I ran across this null exception problem when I tried replacing the image source binding with my solution that calls the same property. WPF somehow handles the possible null objects and I'd like to do it the same way to keep things clean.
In BindingBase have two properties: TargetNullValue and FallbackValue.
TargetNullValue returns your value when the value of the source is null.
FallbackValue returns your value when the binding is unable to return a value.
Example of using:
<!-- xmlns:sys="clr-namespace:System;assembly=mscorlib" -->
<Window.Resources>
<!-- Test data -->
<local:TestDataForImage x:Key="MyTestData" />
<!-- Image for FallbackValue -->
<sys:String x:Key="ErrorImage">pack://application:,,,/NotFound.png</sys:String>
<!-- Image for NULL value -->
<sys:String x:Key="NullImage">pack://application:,,,/NullImage.png</sys:String>
</Window.Resources>
<Grid DataContext="{StaticResource MyTestData}">
<Image Name="ImageNull"
Width="100"
Height="100"
Source="{Binding Path=NullString, TargetNullValue={StaticResource NullImage}}" />
<Image Name="ImageNotFound"
Width="100"
Height="100"
Source="{Binding Path=NotFoundString, FallbackValue={StaticResource ErrorImage}}" />
</Grid>
See this links, for more information:
BindingBase.TargetNullValue Property
BindingBase.FallbackValue Property
Note: The upvoted and accepted answer does not answer the question; it explains how you can get {Binding A} to work if A is null, which is trivial to handle anyway, but it does not explain what happens and how to handle the much more interesting case of {Binding A.B} when A is null, and that is specifically what the question is asking. What follows is the answer to the question as stated.
WPF generally handles the case where A is null when you use A.B in a binding; I have not tried specifically with <Image Source>, but I have tried with <DataGrid ItemsSource> and with <Button Command>.
When WPF handles these cases, what I have observed happening is that there is no error or warning in the output window, and the application malfunctions a bit, but it does not crash:
In the case of <DataGrid ItemsSource>, the DataGrid appears empty.
In the case of a <Button Command>, the button is clickable, but when you click it nothing happens.
In the case of <Image Source> I would expect that no image will appear.
(Note that all these are cases of silent failure, so whoever decided that WPF should behave this way should be shot by firing squad at the central square with great celebrations and live music and big giveaways.)
The way we generally handle these cases depends on the nature of the element at hand.
For images, if an empty image is acceptable, then you do not need to do anything. If some image must be shown despite the property being null, then the accepted answer probably provides a solution.
For grids, not showing anything when the property is null is probably the desired behavior.
For buttons, the solution is to use an additional binding to the IsEnabled property of the button.
So, for example:
<Button Command="{Binding A.B}" IsEnabled="{Binding HasA}"/>
Where HasA is defined in the viewmodel as follows:
bool HasA => A != null;

SelectedItem of SelectedItem

first of all I would like to thank you for the many good posts that i read in this forum. Unluckily I could not find anything of help for my current problem (either here or anywhere else).
What I'm trying to do sounds quite simple, but I have no clue how to get it to work ... perhaps I'm still to new to wpf or I don't thing wpfy enough :)
I'm designing a front end for a part in an automated manufacturing:
I have a quantity of places where pallets can be put (but it can be empty as well).
Each pallet has up to 3 places where parts can be mounted
Everything is created dynamically of a database and is reacting to changes.
The position of the parts on the pallet comes from the database as well and should be visualized
What I would like to have is:
An overview over the pallet-places with a preview of the pallet
When I select a place I want to see a detail view of the place
When I click on a part on the pallet of the detailed pallet I want to see details to the part
The first two points are quite simple and work nicely:
I have got a DataTemplate for every component (part, pallet, pallet-place). Actually those are UserControls that are imported as Datatemplates
the overview is a ListBox with the places as DataContext
for the detail-place-view I use the UserControl and bound it to the SelectedItem of the Listbox
I tried to bind the Text of a Textblock to the ID of the selected Part ... and fail.
Probably I could use some global variables in the code behind - but that sound very ugly.
Can anybody help?
I have got a solution ... it is not nice but works.
I created an event in the pallet, that triggers, when the selected part-place changes
I handle the event in the pallet-place and create a new one
And finally I handle it in the overview and change the detailview accordingly
Most likely there are much nicer solutions, but it will suffice.
Perhaps try an ElementName binding?
<TextBlock Text="{Binding ElementName=Name_of_your_Listbox, Path=SelectedItem.ID" />
Can you post a bit more code of your TextBlock and your Binding?
Context is important, if i use a ContentControl and bind its content to the SelectedItem like this:
<ContentControl Content="{Binding SelectedItem, ElementName=mylistbox}">
I can bind to the ID of the selected item in the DataTemplate like this:
<ContentControl.ContentTemplate>
<DataTemplate>
<TextBlock Text="{Binding ID}" />
</DataTemplate>
</ContentControl.ContentTemplate>
That is because setting the Content of the ContentControl automatically sets the DataContext as well, and this binding is relative to the DataContext since no source (ElementName, RelativeSource, Source) has been specified.
I do not know how your UserControl handles the context, if the DataContext is not affected such bindings will not work. You would need to bind directly then:
<uc:MyDetailsView Data="{Binding SelectedItem, ElementName=mylistbox}">
<!-- ... -->
<TextBlock Text="{Binding SelectedItem.ID, ElementName=mylistbox}" />
This of course defeats the purpose of having the binding on the UserControl itself in the first place. But unless you post some relevant code it's quite hard to tell what is wrong.
Also check the Output window in VisualStudio, binding errors will show up there and might provide valuable information as to what went wrong.

WPF: Textbox Binding with StringFormat={}{0:F2}. Don't show zero's

I am binding an object to a TextBox with the following XAML:
<TextBox Name="MyTextBox" Text="{Binding Path=MyValue, Mode=TwoWay, StringFormat={}{0:F2}}" />
Naturally when I bind a new object (which values are all still zero) the Text property is set to 0.00. I have several of these TextBoxes, which makes it tedious to delete every value before entering a new one.
At the moment I'm clearing these boxes in the Window_Loaded method using the FindVisualChildren method.
It just feels clunky though. Is there a neat way of doing this?
Try the following:
StringFormat={}{0:#.##}
It will format to two decimal places and won't show zeroes.

WPF Binding Help

I haven't used WPF that much so the solution to this is probably pretty easy.
In the ide I'm developing it will have multiple controls(text editor) each being hosted in a tab, much like VS does for each source file. When the user clicks new the "host" creates a new EditorWindow(a usercontrol), creates a new tab, and tells the tab to display the EditorWindow it created, and then updates a property called currentWindow (of type EditorWindow) with the one that's currently active. Inside the EditorWindow is the text editor whose name is textEditor(also a property). What I'm trying to do is take this code from the quick start source of the text editor control I'm using
<StackPanel>
<CheckBox Checked="EditiorOptionsChecked" IsChecked="{Binding ElementName=Control, Path=currentWindow.textEditor.IsIndicatorMarginVisible}" Content="Indicator margin visible" />
<CheckBox Checked="EditiorOptionsChecked" IsChecked="{Binding ElementName=Control, Path=currentWindow.textEditor.IsLineNumberMarginVisible}" Content="Line number margin visible" />
<CheckBox Checked="EditiorOptionsChecked" IsChecked="{Binding ElementName=Control, Path=currentWindow.textEditor.IsRulerMarginVisible}" Content="Ruler margin visible (useful for fixed-width fonts only)" />
<CheckBox Checked="EditiorOptionsChecked" IsChecked="{Binding ElementName=Control, Path=currentWindow.textEditor.IsSelectionMarginVisible}" Content="Selection margin visible" />
</StackPanel>
put that in the host controls xaml, and bind the checkboxes to the syntax editor. I've tried a couple different things to no avail. Control is the name of the window hosting all the tabs, and path is obviously supposed to be the property that the checkboxes are bound too. I'm pretty sure the problem is that at initial run-time currentWindow isn't initialized so therefore my bindings aren't ever getting updated, but I'm at a loss as to how to fix this issue. Thanks!
Since you are new to WPF, you may not know that properties have to implement some sort of change notifications in order for bindings to work. For instance, if any of the properties in the the path "currentWindow.textEditor.IsIndicatorMarginVisible" change, you need to inform the binding engine that it has changed. If you implement these properties as DependencyPropertys, the change tracking comes for free. Otherwise, you should implement INotifyPropertyChanged.
I've found that the Snoop utility is the easiest way to do quick binding debugging, you should try using it and see if it tells you anything useful on the bound properties.

Resources