Adjust the Visibility property of a View not working - wpf

I've a strange problem with binding a boolean property to a View's Visibility property.
I have a 'main' View that contains a bunch of other Views as well as various other UIElements including Buttons, TextBoxes, Grids, StackPanels and some telerik controls. Some of the controls have their visibility bound to boolean properties on my ViewModel, such that when the property is positive they are shown, and when negative they are collapsed.
<Border Visibility="{Binding IsSectionShown,
Converter={StaticResource BoolToVisibilityConverter}}" >
This is working perfectly for me. Obvious I have trigger the notification event in the IsSectionShown setter, and the control's Visibility is adjusted accordingly.
Now I have a View which needs to have its visibility adjusted. The obvious implementation is
<vw:ActivityView DataContext="{Binding Activity}"
Visibility="{Binding IsPositive,
Converter={StaticResource BoolToVisibilityConverter}}" />
Does not work! My work around is to wrap my view inside a StackPanel and adjust the visibility of the StackPanel - and this works fine:
<StackPanel Visibility="{Binding IsPositive,
Converter={StaticResource BoolToVisibilityConverter}}">
<vw:ActivityView DataContext="{Binding Activity}" />
</StackPanel>
Any ideas as to why this is happening? Workaround is fine but I would like to identity the gap in my understanding.

For both of these to work, the IsPositive property would have to exist both inside Activity and one level up in the data context that Activity comes from. But that's probably not what you intended. Instead, you can use something like this so that the visibility comes from a different data context than the one that applies to the view itself:
<vw:ActivityView DataContext="{Binding Activity}"
Visibility="{Binding IsPositive, ElementName=ParentElement,
Converter={StaticResource BoolToVisibilityConverter}}" />
where ParentElement is the parent element that contains vw:ActivityView.

Related

How to handle Validations on Custom Control

I recently wrote my first custom control, an autocomplete textbox. Its Controltemplate consists of something like this
<Grid >
<Border/>
<TextBlock x:Name="Label"/>
<TextBox x:Name="TextLabel"/>
</Grid>
The first Textblock is used as a Label, the second one shows the content. The TextLabel binds on an Object, let's call it Customer If the underlying search doesn't find a Customer object, I want to show the errortemplate. When defining the TextLabel like this
<TextBox x:Name="PART_Editor"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
Validation.ErrorTemplate="{DynamicResource ValidationErrorTemplate}"
Style="{StaticResource TransparentTextBoxStyle}"
Text="{Binding Path=Text, RelativeSource={RelativeSource Mode=TemplatedParent},
Mode=TwoWay, ValidatesOnNotifyDataErrors=True,
NotifyOnValidationError=True,
ValidatesOnDataErrors=True,
UpdateSourceTrigger=PropertyChanged}" >
</TextBox>
the Validation is made and the error template of the textbox is shown. Unfortunately the Red Border is only around the inner TextBox and not around the whole custom control which looks just not good.
I was wondering how to achieve two things:
How can the ErrorTemplate of the CustomControl be triggered when one of the child-validations fail?
Do I have to specify all these NotifyOnValidationerror properties or is it possible to catch all errors on entity level and show the same ErrorTemplate
If you need additional Information, please just ask

override IsEnabled property for Custom Control DualButton to set Visibility

I am working on WPF and have little knowledge of XAML customly created controls.
I have a custom control name 'DualButton' as follows :
<Controls:DualButton x:Name="StandardConferenceCancelButton"
Width="90"
Height="25"
Margin="2"
LeftButtonCommand="{Binding StandardModeConnectCommand}"
RightButtonCommand="{Binding ConferenceCancelCommand}"
>
<AccessText HorizontalAlignment="Center" Text="{x:Static I18N:TelephonyRegionViewRes.Standard}" />
</Controls:DualButton>
its 2 dependancy properties 'LeftButtonCommand' and 'RightButtonCommand'binds two different ICommands.
I want to set Visibility of this button to CanExecute of LeftButtonCommand so that when LeftButtonCommandCanExecute() returns true, that time only button gets visible.
I took dependancyProperty 'IsEnabled' what further I need to do in this
I know it's late, but might help others...
In your DataContext, create a property like IsVisible that returns
StandardModeConnectCommand.CanExecute()
In your window or user control, add the resource
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
</Window.Resources>
In your dual button, after or before the commands, add:
Visibility="{Binding IsVisible, Converter={StaticResource BooleanToVisibilityConverter}}"
Finally, in the places where the returned value of CanEecute is likely to change, add in your datacontext a
NotifyPropertyChanged(nameof(IsVIsible));
You should be on track with this.

How to define DataContext in my Resource File or under Window.Resource tag?

I have this binding:
<Window x:Name="_local">
<TextBox x:Name="txtVendorName" DataContext="{Binding ElementName=_this, Path=VendorObject}" Width="200" Height="50" BorderBrush="Black" Text="{Binding Path=VendorName}" />
if i have 50 textboxes and label which I need to bind, do I need to put DataContext for all??
Is there a way I can centralize this DataContext and only define Text/Content for my objects?
I don't want to define DatContext to my Grid. So how can I define DataContext in my?
<Window.Resources></Window.Resources>
If I am guessing your actual requirement right, then what you want is all 50 labels and textblocks should be bound to the data context which is VendorObject from _this object. Although I couldnt really guess what _this object is.
Well DataContext is an Inherited Dependency Property (IDP) what they mean is when a visual parent is set with a data context its data context is acquired by all the children below that visual.
So if you put some Panel in your window and set its data context once with your binding DataContext="{Binding ElementName=_this, Path=VendorObject}" and then put all those 50-100 textblocks and labels under that panel then they will automatically acquire that vendor-object as the data context.
So
<StackPanel DataContext="{Binding ElementName=_this, Path=VendorObject}">
<TextBlock Text="{Binding Path=VendorName}" />
<TextBlock Text="{Binding Path=VendorId}" />
<TextBlock Text="{Binding Path=VendorLocation}" />
.... <!--Put all the 50 UI items here to use same data context -->
</StackPanel>
I hope I guessed correctly of what you need.
Now answering you next question,
So how can I define DataContext in my?
<Window.Resources></Window.Resources>
You cant. But you can create an instance of VendorObject class and give it a resource Key, but thats simply a bad design.

WPF XAML Binding

Hello
I have a problem with a binding that I want to do and can't find any information on how to do it.
Basically I want to bind an object to a property of another object.
For example
<TextBox Text="test" Tag="{Binding ElementName=TxtBx2}" x:Name="TxtBx1"/>
<TextBox Text="test" x:Name="TxtBx2"/>
This is kind of weird but it would help on the code that i'm implementing, so on a property of one object I want to have another object bind in xaml.
I don't know if this is possible, any pointers would be helpful
Thanks, Ruben
That is how you do it; you just need to specify the Path.
<TextBox Text="test" Tag="{Binding ElementName=TxtBx2, Path=Text}" x:Name="TxtBx1"/>
<TextBox Text="test" x:Name="TxtBx2"/>
If you are wanting the DataContext of the TextBox; then your Path would change accordingly.
<TextBox Text="test" Tag="{Binding ElementName=TxtBx2, Path=DataContext}" x:Name="TxtBx1"/>
<TextBox Text="test" x:Name="TxtBx2"/>
If you are needing to use the Tag property within a WPF application you might want to re-evaluate your approach as I have yet to use the Tag property since moving from WinForms as that need has been replaced by leveraging the data binding functionality within WPF.
UPDATE:
If your goal is to bind to a given control versus a property on the control; then don't specify the property name within the Path.
Based on your goal; attached behaviors would be a better approach and allow you to wrap the functionality within the extended DataGrid.
<TextBox Text="test" Tag="{Binding ElementName=TxtBx2,Path=Text}" x:Name="TxtBx1"/>
<TextBox Text="test" x:Name="TxtBx2"/>
Assuming you want the value of the Text property of TxtBx1 to be the value of the Text property in TxtBx2, you would use:
<TextBox x:Name="TxtBx1" Text="{Binding ElementName=TxtBx2, Path=Text}" />
<TextBox x:Name="TxtBx2" Text="test" />
Update
Assuming (possibly incorrectly again!) that you want to bind the TxtBx1 element to the Tag of TxtBx2, you would use:
<TextBox x:Name="TxtBx1" Text="test" />
<TextBox x:Name="TxtBx2" Tag="{Binding ElementName=TxtBx1}" Text="test" />
Just out of interest, why do you want to do such a thing?
Update 2
Assuming that you have a Datagrid that you've extended from the wpftoolkit datagrid and a user control that is a pager for that Datagrid, and when you move to another page you need to do some processing on the datagrid, then why don't you just either update the datagrid in your page change event (if using code behind), or update the items that the datagrid is bound to in your page change verb on your view model (if using MVVM)?
Well, it does make sense to bind to an entire object(not to any specific property) with items control such as this:
<ListBox x:Name="pictureBox"
ItemsSource=”{Binding Source={StaticResource photos}}" …>
......
</ListBox>

Silverlight RelativeSource of TemplatedParent Binding within a DataTemplate, Is it possible?

I'm trying to make a bar graph usercontrol. I'm creating each bar using a DataTemplate.
The problem is in order to compute the height of each bar, I first need to know the height of its container (the TemplatedParent). Unfortunately what I have:
Height="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Height, Converter={StaticResource HeightConverter}, Mode=OneWay}"
does not work. Each time a value of NaN is returned to my Converter. Does RelativeSource={RelativeSource TemplatedParent} not work in this context? What else can I do to allow my DataTemplate to "talk" to the element it is being applied to?
Incase it helps here is the barebones DataTemplate:
<DataTemplate x:Key="BarGraphTemplate">
<Grid Width="30">
<Rectangle HorizontalAlignment="Center" Stroke="Black" Width="20" Height="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Height, Converter={StaticResource HeightConverter}, Mode=OneWay}" VerticalAlignment="Bottom" />
</Grid>
</DataTemplate>
To answer your question RelativeSource only works in a ControlTemplate it doesn't work in a DataTemplate.
Is there a reason why the Silverlight Toolkit Chart controls don't work for you in creating a bar graph (or a Column Chart as the Tookit refers to vertical set of bars).
Have you tried the ActualHeight property? It should return you a value. RelativeSource with the TemplatedParent mode will work in a data template, but it will return the content presenter of the templated control/item, not the control/item itself (which it does when used in a control template). To experiment, put a button in the data template, and assign that binding expression (without the path) to its Tag property. Handle its Click event, and put a breakpoint in the event handler. Now when you run the project and click on the button, the breakpoint will be hit in your code, and you can see the object that it is binding to from the Tag property of the button (which you can see from the sender parameter). Hope this helps...

Resources