I have a problem to modify TemplatedParent from ControlTemplate. My xaml code is:
<RadioButton Name="source" Focusable="True">
<RadioButton.Template>
<ControlTemplate>
<RadioButton Name="target" Focusable="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Focusable, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</ControlTemplate>
</RadioButton.Template>
</RadioButton>
When Focusable in source is changing also Focusable in target should change and Enabled in source and target should change.
For excample:
source.Focucable = false
then
source.IsEnabled = false, target.IsEnabled=false, target.Focusable=false
UPDATED
When I tried solution proposed by Rachel, everything works fine as long as code looks like this:
<RadioButton Name="source"
Focusable="False"
IsEnabled="{Binding Focusable, RelativeSource={RelativeSource Self}}"
Height="19"
HorizontalAlignment="Left"
Width="146" Margin="0,12,0,0" VerticalAlignment="Top">
<RadioButton.Template>
<ControlTemplate>
<RadioButton
Name="target"
Focusable="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Focusable, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
IsEnabled="{Binding Focusable, RelativeSource={RelativeSource Self}}"
IsChecked="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsChecked, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</ControlTemplate>
</RadioButton.Template>
</RadioButton>
Problem occurs in my real application, where I can't set binding in xaml (controls are build dynamically, and templates are reading from resources file) but only in c#.
XAML in this situation looks like this:
<RadioButton Name="source"
Focusable="False"
Height="19"
HorizontalAlignment="Left"
Width="146" Margin="0,12,0,0" VerticalAlignment="Top">
<RadioButton.Template>
<ControlTemplate>
<RadioButton
Name="target"
Focusable="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Focusable, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
IsEnabled="{Binding Focusable, RelativeSource={RelativeSource Self}}"
IsChecked="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsChecked, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</ControlTemplate>
</RadioButton.Template>
</RadioButton>
and c#
Binding bindingRadio = new Binding("RadioButton.Focusable");
bindingRadio.RelativeSource = new RelativeSource(RelativeSourceMode.Self);
source.SetBinding(RadioButton.IsEnabledProperty, bindingRadio);
In xaml source Focusable is set to False, so binding in c# should set IsEnabled also to false. But when I click on radio it is making checked. Where should I put this c# code to make things works as it should be (i tried Window_Load, Radio_Initialized, Radio_Loaded)
Why not just bind the IsEnabled properties to the Focusable properties?
It looks like you're already binding the Focusable property to the template value, so just bind the IsEnabled property to the Focusable one
IsEnabled="{Binding Focusable, RelativeSource={RelativeSource Self}}"
Also, I think as a shortcut for your Focusable binding you can use {TemplateBinding Focusable} instead of binding to the relative source
Related
I am using Syncfusion visual style. I am trying to bind the ToolTip foreground inside the TextBlock present inside the StackPanel for displaying the ToolTip text.But the binding doesn't work properly in the TextBlock.
MainWindow.xaml
<Grid>
<CheckBox Grid.Row="5" Grid.Column="1" HorizontalAlignment="Center" Margin="0,4,10,0" VerticalAlignment="Center" IsChecked="{Binding AutoAdd, Mode=TwoWay}">
<CheckBox.ToolTip>
<StackPanel>
<TextBlock Foreground="{Binding Path=Foreground, Mode=OneWay, RelativeSource={RelativeSource AncestorType={x:Type ToolTip}}}" FontWeight="Bold" FontSize="14" Margin="0,0,0,5">Automatically Add To Path</TextBlock>
<TextBlock Foreground="{Binding Path=Foreground, Mode=OneWay, RelativeSource={RelativeSource AncestorType={x:Type ToolTip}}}">
If this path is associated with the primary configuration,
<LineBreak />
automatically add newly instantiated optical elements to the end of the path.
</TextBlock>
<Border BorderBrush="Silver" BorderThickness="0,1,0,0" Margin="0,8" />
<WrapPanel>
<Image Margin="0,0,5,0" />
<TextBlock Foreground="{Binding Path=Foreground, Mode=OneWay, RelativeSource={RelativeSource AncestorType={x:Type ToolTip}}}" FontStyle="Italic">Press F1 for more help</TextBlock>
</WrapPanel>
</StackPanel>
</CheckBox.ToolTip>
</CheckBox>
</Grid>
Any other work around regarding this issue.
Regards,
Hari Prasad
A Tooltip is in a different datacontext and not directly in the visual tree to a control which appears to be it's parent. Hence, when you search up the visual tree using relativesouce, it will find nothing.
You may use PlacementTarget to reference the thing which is nominally it's parent - checkbox in your markup
"{Binding Path=PlacementTarget.PropertyName, RelativeSource={RelativeSource Self}}"
Here PropertyName is whichever property you want.
That could be DataContext.ViewModelProperty if you wanted a property in your viewmodel.
In this instance I would try
Foreground="{Binding Path=PlacementTarget.Foreground, RelativeSource={RelativeSource Self}}"
Depending on your usage, maybe using a dynamicresource would be simpler though.
This is a more specific description of my problem from a previous question, with a follow-up answer.
I had a standard hyperlink defined in XAML:
<TextBlock>
<Hyperlink IsEnabled="{Binding LinkEnabled}">
<TextBlock Text="{Binding Text}"/>
</Hyperlink>
</TextBlock>
The hyperlink's IsEnabled property is bound to a property on the view model, the value of which can change. I needed to place a tooltip on the hyperlink which would only be displayed if the hyperlink is disabled.
To show the tooltip only when the hyperlink is disabled, the ToolTipService.ShowOnDisabled and ToolTipService.IsEnabled (with the negation converter) properties must be set on the hyperlink:
<TextBlock>
<Hyperlink IsEnabled="{Binding LinkEnabled}"
ToolTip="ToolTip"
ToolTipService.ShowOnDisabled="True"
ToolTipService.IsEnabled="{Binding IsEnabled, RelativeSource={RelativeSource Self}, Converter={StaticResource negateConverter}}">
<TextBlock Text="{Binding Text}"/>
</Hyperlink>
</TextBlock>
However, the tooltip won't be shown, since once the hyperlink is disabled, it stops being hit-testable, because it is contained in the TextBlock (or so I understood).
Thus, the solution would be to change the "IsEnabled" property on the parent TextBlock, not on the hyperlink.
However, this works:
<TextBlock IsEnabled="False">
But this doesn't:
<TextBlock IsEnabled="{Binding LinkEnabled}">
In the latter case, changing the TextBlock's IsEnabled property will not change the hyperlink's IsEnabled property. To solve this issue, the hyperlink's IsEnabled property must be bound to the parent's property.
And here is the actual solution, all put together:
<TextBlock IsEnabled="{Binding LinkEnabled}">
<Hyperlink IsEnabled="{Binding IsEnabled, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type FrameworkElement}}}"
ToolTip="ToolTip"
ToolTipService.ShowOnDisabled="True"
ToolTipService.IsEnabled="{Binding IsEnabled, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type FrameworkElement}}, Converter={StaticResource negateConverter}}">
<TextBlock Text="{Binding Text}"/>
</Hyperlink>
</TextBlock>
I have this problem so that I can see nothing during WPF design.
Here is the WPF code at the begging:
<UserControl x:Class="VolumeControlInterface.VolumeControlInterface"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vtkVC="clr-namespace:VtkVolumeControl;assembly=VtkVolumeControl"
xmlns:local="clr-namespace:VolumeControlInterface"
Height="700" Width="700" Margin="5"
Here is my WPF code wiggled underneath:
<Grid DataContext="{Binding RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}">
<vtkVC:VolumeRenderer Name="VolumeControl" Width="Auto" Height="Auto" Margin="5" Grid.Column="0"
LowerThresholdChanA="{Binding Path=BlackPoint0, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
UpperThresholdChanA="{Binding Path=WhitePoint0, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
LowerThresholdChanB="{Binding Path=BlackPoint1, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
UpperThresholdChanB="{Binding Path=WhitePoint1, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
LowerThresholdChanC="{Binding Path=BlackPoint2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
UpperThresholdChanC="{Binding Path=WhitePoint2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
LowerThresholdChanD="{Binding Path=BlackPoint3, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
UpperThresholdChanD="{Binding Path=WhitePoint3, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
IsChanASelected="{Binding Path=IsChanASelected, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
IsChanBSelected="{Binding Path=IsChanBSelected, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
IsChanCSelected="{Binding Path=IsChanCSelected, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
IsChanDSelected="{Binding Path=IsChanDSelected, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
DataSpacingZ="{Binding Path=DataSpacingZ, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
DataSpacingZMultiplier="{Binding Path=DataSpacingZMultiplier, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
FolderDirectory="{Binding Path=ZStackCacheDirectory, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
HardwareSettingsFile="{Binding Path=HardwareSettingsFile, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
TileIndex="{Binding Path=TileIndex, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
WellIndex="{Binding Path=WellIndex, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
TimePointIndex="{Binding Path=TimePointIndex, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
TotalSystemChannels="4"
Timepoints="1">
</vtkVC:VolumeRenderer>
</Grid>
This project is VolumeControlInterface, which imports VtkVolumeControl.dll as reference from another project. VolumeRenderer is a class in VtkVolumeControl. The VtkVolumeControl is built successfully and the whole project functions with no problem. It is just I cannot see anything during design of VolumeControlInterface, and it says "Could not create a instance of type 'VolumeRender'"
I have tried:
Remove VtkVolumeControl, and re-add it. Not working.
Using if (!System.ComponentModel.DesignerProperties.GetIsInDesignMode(this)) in the constructor, not working either.
I am wondering what is going on here, and how I should make the design visible?
EDIT:
I am using VS2008, WINDOWS 7 64BIT
Also, every time I build vtkVolumeControl.dll, the reference in VolumeControlInterface will show a warning, says cannot find the vtkVolumeControl.dll; But if I go ahead build VolumeControlInterface regardless, it won't have any problem, and it seems to manage to find vtkVolumeControl.dll.
EDIT:
This is how it looks:
What do you want to achieve with the following line?
<Grid DataContext="{Binding RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}">
because you are using the UserControl as Binding, which I assume is not what you want.
try the following to access the datacontext of the UserControl
<Grid DataContext="{Binding Path=DataContext, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}">
i've created a Datagrid Control in WPF. how can i make my Button visible only for a Cell
inside the row that i have select it.
anyone can help.
XAML:
<DataGridTemplateColumn x:Name="typ" Header="H." Width="50">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Name="btnTabelle" Visibility="Hidden" Height="20" Width="25"
Click="Button_Table_Click">
</Button>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
You can set the Visibility based on if the DataGridCell.IsSelected, although you will need a BooleanToVisibilityConverter to convert the boolean value to a Visibility one
Here's an example, using a RelativeSource binding to find the DataGridCell
<Button Visibility="{Binding Path=IsSelected,
RelativeSource={RelativeSource AncestorType={x:Type DataGridCell}},
Converter={StaticResource MyBooleanToVisibiltyConverter}" ... />
I'm trying to bind the SelectedItem to a View. But the view is not able to access the viewmodel when it is inside the Resources block.
When the datacontext is re-assigned to the children, the binding works for textblocks but not for UserControl (NoteView)
Am I missing any Binding?
PFB revised(entire) code and inline comments.
<UserControl x:Class="Konduva.View.NoteSearchView"
<!-- other namespaces here -->
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
DataContext="{Binding NoteSearch, Source={StaticResource Locator}}">
<Grid>
<ListView ItemsSource="{Binding Notes}"
SelectedItem="{Binding SelectedNote}">
<ListView.Resources>
<DataTemplate DataType="{x:Type vm:NoteViewModel}">
<DockPanel>
<TextBlock Text="{Binding Title}" />
<Popup Placement="Right"
PlacementTarget="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=ListViewItem}}"
IsOpen="{Binding (ListViewItem.IsSelected), RelativeSource={RelativeSource FindAncestor, AncestorType=ListViewItem}}"
DataContext="{Binding Path=DataContext, RelativeSource={RelativeSource AncestorType={x:Type ListView}}}">
<StackPanel>
<!-- This is working --> <TextBlock Text="{Binding SelectedNote.Title}" />
<!-- This is not working --> <v:NoteView DataContext="{Binding SelectedNote}" />
</StackPanel>
</Popup>
</DockPanel>
</DataTemplate>
</ListView.Resources>
</ListView>
</Grid>
</UserControl>
NoteView:
<Grid>
<TextBlock Text="{Binding Title}" /> // This Text is not displayed
</Grid>
Update 3
Since you're using MvvmLight: in NoteView, try changing
DataContext="{Binding Note, Source={StaticResource Locator}}"
to
<UserControl.Style>
<Style TargetType="UserControl">
<Setter Property="DataContext" Value="{Binding Note, Source={StaticResource Locator}}"/>
</Style>
</UserControl.Style>
Update 2
Encountered a similar problem a few minutes ago which I didn't fully understand so I'll throw in the same solution here to see if it helps. What happends if you change it to this?
<v:NoteView DataContext="{Binding RelativeSource={RelativeSource AncestorType={x:Type Popup}},
Path=DataContext.SelectedNote}"/>
Update
I'm unable to reproduce this. Try adding this in your NoteView constructor. Do you reach DataContextChangedHandler when you change the selection in the ListView?
public NoteView()
{
InitializeComponent();
DependencyPropertyDescriptor dpd =
DependencyPropertyDescriptor.FromProperty(UserControl.DataContextProperty,
typeof(UserControl));
if (dpd != null)
{
dpd.AddValueChanged(this, new EventHandler(DataContextChangedHandler));
}
}
void DataContextChangedHandler(object sender, EventArgs e)
{
MessageBox.Show("DataContext Changed: " + DataContext);
}
First answer
Your DockPanel will get the NoteViewModel as a DataContext and not the ListView and since this DataContext is inherited by all Childs every child will end up with a NoteViewModel as DataContext. To use the ListView as a DataContext for the Popup you can do this. I'm not sure what the DataContext Binding for the StackPanel does though, so I might be missing something here..
<DataTemplate DataType="{x:Type vm:NoteViewModel}">
<DockPanel>
<TextBlock Text="{Binding Title}" />
<Popup Placement="Right"
PlacementTarget="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=ListViewItem}}"
IsOpen="{Binding (ListViewItem.IsSelected), RelativeSource={RelativeSource FindAncestor, AncestorType=ListViewItem}}"
DataContext="{Binding Path=DataContext, RelativeSource={RelativeSource AncestorType={x:Type ListView}}}">
<StackPanel>
<TextBlock Text="{Binding SelectedNote.Title}" />
<StackPanel>
<v:NoteView DataContext="{Binding SelectedNote}"/>
</StackPanel>
</StackPanel>
</Popup>
</DockPanel>
</DataTemplate>
Instead of inserting a NoteView directly and binding the DataContext, use a ContentPresenter:
<ContentPresenter Content="{Binding SelectedNote}>
<ContentPresenter.ContentTemplate>
<DataTemplate>
<v:NoteView />
</DataTemplate>
</ContentPresenter.ContentTemplate>
</ContentPresenter>