WPF Binding on startup - c#

In my WPF project, I have the Visibility of a Grid bound to a bool with a BooleanToVisibilityConverter:
<Grid ... Visibility="{Binding SelectedElement.HasError, Converter={StaticResource ResourceKey=BoolToVis}}">
However on startup the grid is always shown for a few milliseconds, even though the element/class holding the bool field is not even created, and after creation is defaulted to false.
How can I prevent the grid from showing up on startup? I tried to implement a FallbackValue for the binding, because the object in the path is not yet available, but setting "Visible" or "Hidden" here doesn't change anything.

(Posted on behalf of the OP).
Works fine with FallbackValue=Collapsed.

Related

Grid size doesn't bind to parent container's size

I'm trying to bind the size of a Grid to the size of the parent container (Relativepanel with size on auto, named 'MainPanel') in the XAML of a Page like this:
<Grid Width="{Binding ElementName=MainPanel, Path=ActualWidth}">
After doing so, it works in the Designer, but as soon as I run the App it shrinks again (and does so in the Designer).
I've also tried:
<Grid Width="{Binding ActualWidth, ElementName=MainPanel}">
And removed all of my code interacting with the controls.
What is the problem here?
(Universal Windows App in VS 2019)
ActualWidth is not a DependencyProperty and bindings see only first value of this property, which is 0 at the time when they are applied. You have to manually handle SizeChanged event with event handler or custom behavior: https://learn.microsoft.com/en-us/uwp/api/windows.ui.xaml.frameworkelement.sizechanged?view=winrt-19041
Yep, I saw this problem, it does not work within UWP platform, but works well in WPF platform. please refer ActualHeightProperty remark part
Although it has an ActualHeightProperty backing field, ActualHeight does not raise property change notifications and it should be thought of as a regular CLR property and not a dependency property.
For your requirement, you could use Microsoft.Toolkit FrameworkElement Extensions to make actual size binding avaiable.
Install Microsoft.Toolkit.Uwp.UI.Controls nuget, then set extension like the following
xmlns:ui="using:Microsoft.Toolkit.Uwp.UI"
......
<RelativePanel
x:Name="MainPanel"
ui:FrameworkElementExtensions.EnableActualSizeBinding="True"
SizeChanged="MainPanel_SizeChanged">
<Grid
Width="{Binding ElementName=MainPanel, Path=(ui:FrameworkElementExtensions.ActualWidth)}"
Height="100"
Background="SeaGreen" />
</RelativePanel>
For more detail please refer this tutorial.

Control ItemsSource binding does not update on ClickOnce Web Published WPF app

I have a WPF application with an XAML Window containing a few Buttons and a DataGrid. When buttons are pressed, some logic is performed in the background which builds a list of some type and finally assigns the list to a (MVVM) model property "DataSource" to which an ItemsSource of the DataGrid is bound to like:
<DataGrid x:Name="DataGrid" Grid.Row ="10" ...
ItemsSource="{Binding Path=DataSource, Mode=TwoWay, NotifyOnSourceUpdated=True, NotifyOnTargetUpdated=True}">
When the content of DataSource is changed, DataGrid is aware of that and shows the new data. So far all good, application works as intended and with no problems. I can copy the bin output of build and sucessfully run it just about everywhere.
Then comes ClickOnce publish. If published so that it installs from, and is installed from an Unc network share, e.g. \SomeServer\SomePath\InstallFromDir\, everything still works fine.
But if published so that it installs from, and is installed from an online url, e.g. http://companydomain.com/InstallFromDir/, DataGrid simply does not update.
Nothing else is changed but the method of app and updates availability from unc to web.
What I gathered from debugging trace points still applies. The list in the background is built anew. It is assigned to the DataSource property (if I verify the contained data, it does contain the new data). But if I access the DataGrids ItemsSource it still contains the OLD, initial data.
I have tried re-assigning the DataSource to ItemsSource -- doesn't help. I have tried re-binding the data when it changes programatically, as in:
var sourceBinding = new System.Windows.Data.Binding
{
Path = new PropertyPath("DataSource"),
Mode = BindingMode.TwoWay,
NotifyOnSourceUpdated = true,
NotifyOnTargetUpdated = true
};
BindingOperations.SetBinding(((MainWindow)_window).DataGrid,
System.Windows.Controls.DataGrid.ItemsSourceProperty, sourceBinding);
and even changing the xaml so that it is ONLY bound in code:
<DataGrid x:Name="DataGrid" Grid.Row ="10" ... >
and it still works the same as described above: works as direct copy or unc install, but doesn't work as web install.
I am totally lost as to either finding the cause or finding the workarounds. Anyone encountered this before? Any ideas? Many thanks!
Update: I have initially thought this was a DataGrid issue, but I have since also tried replacing DataGrid with ListView, and it doesn't work either.

Handling different view model states in MVVM

I’m using the MVVM pattern for my metro app. On my main page, the user presses a button and the app gets the current location of the user.
The process of getting the user’s location is asynchronous and I want the UI to change, so the button will be disabled and an indeterminate progress bar will display until the co-ordinates are returned.
What is the best way to manage this according to MVVM? Having a custom visual state? I notice that there are ApplicationViewStates and CommonStates, is it possible to add your own custom ones?
How would you do this?
I think you're looking for something like:
viewModel:
private async void CommandExecution()
{
IsAwaitingResponse=true;
var response = await _myService.DoNetworkCall()
IsAwaitingResponse=false;
}
If you're using one of the microsoft templates you should have a BooleanToVisibilityConverter sitting in your "Common" folder. You use it like so:
<Page.Resources>
<BooleanToVisibilityConverter x:key="booleanToVisibilityConverter"/>
</Page.Resources>
"..."
<ProgressBar Visibility={Binding IsAwaitingResponse,Converter={StaticResource booleanToVisibilityConverter}}" IsIndeterminate="true"/>
My xaml experience is with WPF and Silverlight, but I hope this suggestion works for a Metro app. You can bind the button's IsEnabled property and the progress bar's visibility property to a boolean property (maybe call it IsCurrentLocationComplete) on your view-model. You'll change this property's value when the async method is complete and your view will be updated. Setting the Button's property is straight forward, but you'll need a value converter (IValueConverter) for the progress bar's visibility one.

TextBlock width binding to GridView

On my XAML page I have a text block with following binding:
<TextBlock Width="{Binding ActualWidth, ElementName=SessionList, Mode=OneWay}" ... />
This binds to a grid view:
<GridView x:Name="SessionList" ItemsSource="{Binding Sessions}"... />
Now when the page first loads and data is available, the text block will be visible and have the correct width. When the page loads and there is no data, the text box will not be visible because of the bound width.
But ... when I load up data in the background and after a while the data comes in (through MVVM) the list will be show, but the text block width will not change accordingly, and setting it as TwoWay has no effect.
Any ideas/tips?
ActualWidth is not a property that you can bind to within WinRT. Not sure if you are showing static text or bound text. If bound text and data is same as GridView has then it should go away if data is null. If static data, then use a ValueConverter to set the visibility of the TextBlock based on the data being null/empty
Binding issues like this are usually caused by properties that are not bindable, i.e. they are not dependency properties and/or do not implement INotifyPropertyChanged. Whatever. I use a Attached Dependency Property or, if that does not cover enough, a behavior. Now behavior are not included in WinRT, but that problem has already been addressed ;-)

Custom UserControl "IsEnabled" data binding not working

I have a kinda awful problem with my WPF application right now...
I have a custom UserControl used to edit details of a component. It should start by being not enabled, and become enabled as soon as the user chose a component to edit.
The problem is: the IsEnabled property does not even change.
Here is my code:
<my:UcComponentEditor Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
IsEnabled="{Binding EditorEnabled}"
DataContext="{Binding VmComponent}" />
EditorEnabled is a property in my ViewModel (VmComponent), and is by default false, becomes true when the user chose a component or created one
Just for the record, in my ViewModel:
private Boolean _editorEnabled = false;
public Boolean EditorEnabled
{
get { return _editorEnabled; }
set
{
_editorEnabled = value;
OnPropertyChanged("EditorEnabled");
}
}
When I try to launch my app, the UserControl is starting... enabled.
I added breakpoints everywhere, the EditorEnabled is false from the beginning.
I also did a horribly stupid thing to try to figure out what's happening: I created a converter (so useful -- converting a boolean to boolean -- eh), put a breakpoint on it, and... The code is never reached.
<my:UcComponentEditor Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
IsEnabled="{Binding EditorEnabled, Converter={StaticResource BoolConverter}}"
DataContext="{Binding VmComponent}" />
That probably means that the property isEnabled is never set, since the converter is never reached.
Do you see any kind of problem there? I started working in WPF about one week ago and therefore I may have missed something essential...
Thank you very much for your time :-)
You should add a DependencyProperty for the binding to work properly. See here for more information.
Code-behind:
public static readonly DependencyProperty EditorEnabledDependencyProperty = DependencyProperty.Register("EditorEnabled", typeof(bool), typeof(UcComponentEditor), new PropertyMetadata(false));
public bool EditorEnabled
{
get { return (bool)base.GetValue(UcComponentEditor.EditorEnabledDependencyProperty); }
set { base.SetValue(UcComponentEditor.EditorEnabledDependencyProperty, value); }
}
The issue I think is that there is a binding on the DataContext property of the user control. Which means the EditorEnabled property should be a property in the VmComponent object. At least that's what my problem was.
To get around it, I specified a proper source to the binding of IsEnabled. Once I did that the control started working as expected.
Hope that helps.
Encapsulating your control in a DockPanel (for example) will remove the need for a DependencyProperty.
You can then simply do your binding with the dockpanel instead of the custom control. Setting the variable bound to IsEnabled on the Dockpanel will automatically enable or disable the items contained in the Dockpanel.

Categories