Dynamic binding to any tab control - WPF - wpf

I am trying to set the max width of the grid of a view, however I want to be able to put this view anywhere within any tab control, as the width of the grid is determined by the tab control it's within. I don't want to have to specify the specific tab control by name because I want it to work with any tab control.
Does anyone know how I can change the below XAML code? This is in the WeUserControl view
<Grid.MaxWidth>
<MultiBinding Converter="{StaticResource WeMaxWidthConverter}">
<Binding ElementName="mainWindowTabControl" Path="ActualWidth"/>
</MultiBinding>
</Grid.MaxWidth>
In the view that it is being used in, it is literally just:
<views:WeUserControl Grid.Column="0" Grid.Row="1" />
and that is encapsulated in a tab control, in this case, called mainWindowTabControl

It's just the tabcontrol you're looking for and the grid will be within the visual tree of this.
The relativesource binding would be:
<Binding Path="ActualWidth"
RelativeSource="{RelativeSource AncestorType={x:Type TabControl}}" />

If you add a public property called "TabControl" to the parent window that returns a reference to the TabControl, you should be able to bind to it like this from any child element of the window:
<Binding Path="TabControl.ActualWidth"
RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type Window}}" />

Related

WPF - Binding a Line with a converter that returns a Line

I'm attempting to draw some scatter charts with WPF, and struggling to draw the little tick marks usually present on chart axes. My view model defines the positions of the ticks using a List<Tick> for each axes, where each Tick item is just the cartesian coordinate of where the tick would fall on the axis. I have an IMultiValueConverter which uses the canvas size to convert the single point into a Line object that can be rendered... but how do I bind this? WPF wants me to specify X1, X2, Y1, and Y2, but I just want to give it the line.
My thought was to define a data template like the following, but it does not compile because I can't give Line a multibinding directly. Is there an intermediate element / attribute I could be using?
<DataTemplate DataType="{x:Type viewModel:Tick}" x:Key="TickTemplate">
<Line>
<WhatsMissing?>
<MultiBinding Converter="{StaticResource PointsConverter}">
<Binding Path="Points"/>
<Binding Path="DataContext.MinPoint" RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type UserControl}}"/>
<Binding Path="DataContext.MaxPoint" RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type UserControl}}"/>
<Binding Path="ActualWidth" ElementName="ChartCanvas"/>
<Binding Path="ActualHeight" ElementName="ChartCanvas"/>
</MultiBinding>
</WhatsMissing?>
</Line>
</DataTemplate>
You could bind a ContentControl's Content property to the Line returned from you converter, but IMO a converter should not deal with UIElements. Creating and manipulating UIElements in code behind should generally be avoided.
Better return a LineGeometry from your converter, and bind a Path's Data property to the result:
<DataTemplate DataType="{x:Type viewModel:Tick}" x:Key="TickTemplate">
<Path Stroke="Black" StrokeThickness="1">
<Path.Data>
<MultiBinding Converter="{StaticResource PointsConverter}">
...
</MultiBinding>
</Path.Data>
</Path>
</DataTemplate>

Binding a unit label in WPF textbox

I'm binding a pressure to a textbox. The pressure could be in PSI, KPA, BARS, etc. I would like to display the unit inside the textbox next to the value. There doesn't seem to be a way to bind the Units string property in my viewmodel to the StringFormat option of the value binding. Is there any way to accomplish this without retemplating the textbox?
You can use MultiBinding:
<TextBox>
<TextBox.Text>
<MultiBinding StringFormat="{}{0} {1}">
<Binding Path="Pressure" />
<Binding Path="Unit"/>
</MultiBinding>
</TextBox.Text>
</TextBox>

Problem with validation and multibinding

In my WPF application I use the following xaml:
...
<TextBox
services:TextBoxService.IsFocused="{Binding Path=IsSelected, Mode=OneWay}"
FocusVisualStyle="{x:Null}">
<MultiBinding
Converter="{StaticResource mconv_operableToString}"
UpdateSourceTrigger="PropertyChanged">
<Binding
Path="Value"
Mode="TwoWay"
NotifyOnValidationError="True" />
<Binding
RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type UserControl}}"
Path="DataContext.Status"
Mode="OneWay" />
</MultiBinding>
The view model class which the first binding uses implements IDataErrorInfo for validation purposes. The problem is that although the error is caught in the property setter, the UI doesn't notice it. I have a style defined with an error template which should be applied when any error occurs in the text box. I suppose that maybe this scenario is not allowed with multi binding because where I use single binding everything works fine.
Thanks in advance.
It seems to me that nobody knows the answer to this but I suppose that this scenario just doesn't work. I'll try to answer it in case somebody will need it. I've tried to bind my View to my View Model class which implements IDataErrorInfo, in xaml I specified a converter and although everything worked fine, the Errors just didn't show up on the UI. So, I removed the converter from the binding and implemented that logic inside the View Model and, voila now everything works fine.

WPF, passing variable to converter inside data template

I assume this is possible but not sure how to do it. I need to pass the value of a class level variable to a converter, from within side a data template.
<DataTemplate x:Key="ResponseItemTemplate">
<StackPanel Orientation="Horizontal" >
<StackPanel.Visibility>
<MultiBinding Converter="{StaticResource VisibilityConverter}">
<Binding Path="Key"/>
<Binding Path="CurrentLanguage"/>
</MultiBinding>
</StackPanel.Visibility>
<TextBox Width="200" Text="{Binding Value}" />
</StackPanel>
</DataTemplate>
The 'Key' value exists on the response item for the data template so this gets passed correctly, whereas the CurrentLanguage is a class variable and I can't get that to pass properly to the converter. Any ideas?
Thanks for the replies, this is what I needed to use in the end:
<Binding Path="DataContext.CurrentLanguage" RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type Window}}"/>
You can use the binding object as follows:
<Binding Source="{x:Static local:DataObject.MyData}" />
See: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/c94682e5-ad16-42f9-973f-fd7588a9c0b5.
If you define the converter as a resource, which you have, you can access it in the code behind. Once you have the converter you can then set a property on it.
var myVisConverter = (VisibilityConverter)window.Resources["VisibilityConverter"];
myVisConverter.CurrentLanguage = ...
EDIT Ok, if you're trying to get access to the parent DataContext from within the DataTemplate, there's a couple of options. Easiest is to name the control with the correct DataContext, then bind to that control like so...
<Binding Path="DataContext.CurrentLanguage" ElementName="nameGivenToElement" />
Josh Smith wrote an article with more ways of getting inherited DataContexts.

Selection checkbox with triggers?

I have this control (see picture). I like when check one option in this control, using styles or with triggers other option enable or disable. This is valid or I have other option for do that?
alt text http://img524.imageshack.us/img524/5819/combos.jpg
Hard to say without seeing your XAML, but you could bind each CheckBox's IsChecked property to the same thing:
<CheckBox.IsChecked>
<MultiBinding Converter="{StaticResource MyConverter}">
<Binding Path="."/>
<Binding Path="SelectedItem" RelativeSource="..."/>
</MultiBinding>
</CheckBox.IsChecked>
The converter (IMultiValueConverter) would then determine whether the first value matches the selected value, and return true/false accordingly.

Resources