Accidently instaniating an viewmodel twice in XAML? [duplicate] - c#

<UserControl x:Class="WatermarkTextBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="30"
d:DesignWidth="250">
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
</UserControl.Resources>
<Border>
<Grid x:Name="grid">
<TextBlock Text="{Binding Watermark, FallbackValue=This prompt dissappears as you type...}"
Visibility="{Binding ElementName=txtUserEntry, Path=Text.IsEmpty, Converter={StaticResource BooleanToVisibilityConverter}}" />
<TextBox Name="txtUserEntry"
Text="{Binding Text, UpdateSourceTrigger=PropertyChanged}" />
</Grid>
</Border>
</UserControl>
The above code shows my WatermarkTextBox control. In the code behind file I have set the DataContext. I left out all the code for the DP's of the control.
public WatermarkTextBox()
{
InitializeComponent();
grid.DataContext = this;
}
I had to bind the DataContext to the grid because otherwise the Text properties of both the watermark and actual text wouldn't display. The problem now is that I can't set the Background of the Border outside of the Grid.
I tried the code below but then only the Background of the Border is set and not the watermark and actual text.
public WatermarkTextBox()
{
InitializeComponent();
this.DataContext = this;
grid.DataContext = this;
}

In a UserControl like this you should never exlicitly set the DataContext to this or anyting else, because the DataContext is usually set externally when you use the UserControl somewhere in your application. The externally applied DataContext is typically (part of) the application's view model.
You should instead change your internal bindings so that they use an explicit RelativeSource:
<TextBlock
Text="{Binding Path=Watermark,
RelativeSource={RelativeSource AncestorType=UserControl},
FallbackValue=This prompt dissappears as you type...}"
Visibility="{Binding ElementName=txtUserEntry,
Path=Text.IsEmpty,
Converter={StaticResource BooleanToVisibilityConverter}}" />
<TextBox
Name="txtUserEntry"
Text="{Binding Path=Text,
UpdateSourceTrigger=PropertyChanged,
RelativeSource={RelativeSource AncestorType=UserControl}}" />
and then remove any DataContext assignment from the UserControl's constructor.
See e.g. this answer (and many other similar) that discuss this topic in detail.

Related

C# WPF: Changing PlacementTarget of a ToolTip

I'm trying to change the PlacementTarget of a ToolTip to a window further up the visual tree in order to have custom ToolTip clipping effects in that window. I've hooked everything up except for the PlacementTarget. Here's an example from XAML and in code...neither work. This style is currently being used for a single tooltip attached to a TextBox.
<Style TargetType="ToolTip">
<Setter Property="ToolTipService.PlacementTarget"
Value="{Binding RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType={x:Type Grid }} }" />
</Style>
If I go into code and look at the tooltip.PlacementTarget once it's attached to something...it's always set to the TextBox. I've tried multiple ways of using the VisualTree to get different UIElements. Nothing seems to work...so I'm assuming I'm not understanding or missing something.
The thing that really gets me is that if I go into my code and look at the PlacementTarget of the tooltip, it won't let me set it to anything else. For instance:
var ancestors = toolTip.PlacementTarget.GetSelfAndAncestors();
foreach(var ancestor in ancestors)
{
if(var ancestor is Grid)
{
// Conditional always hits.
// Before this line, PlacementTarget is a TextBox.
toolTip.PlacementTarget = (UIElement)ancestor;
// After the line, PlacementTarget is still a TextBox.
}
}
What am I doing incorrectly or not understanding?
Edit for Context: The custom clipping effect is to basically just find the closest ancestor window to the ToolTip's target and use that to make sure the ToolTip never goes outside the bounds of that window.
A short sample setting a Tooltip, using a property on the parent Window as PlacementTarget.
<Window x:Class="WpfApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Tag="Bar">
<Window.Resources>
<ToolTip x:Key="FooToolTip">
<StackPanel>
<TextBlock Text="{Binding PlacementTarget.Tag, RelativeSource={RelativeSource AncestorType={x:Type ToolTip}}}"/>
</StackPanel>
</ToolTip>
</Window.Resources>
<Grid>
<TextBlock
Text="Foo"
ToolTip="{StaticResource FooToolTip}"
ToolTipService.PlacementTarget="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
HorizontalAlignment="Center" VerticalAlignment="Center" Height="20" Width="50">
</TextBlock>
</Grid>
</Window>
EDIT
To answer your questions,
the first snippet uses ToolTipService in the wrong way:
The ToolTipService class attached properties are used to determine the placement, behavior, and appearance of a tooltip. These properties are set on the element that defines the tooltip.
Applied in a style:
<Window x:Class="WpfApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
Tag="Bar">
<Window.Resources>
<ToolTip x:Key="FooToolTip">
<StackPanel>
<TextBlock Text="{Binding PlacementTarget.Tag, RelativeSource={RelativeSource AncestorType={x:Type ToolTip}}}"/>
</StackPanel>
</ToolTip>
<Style x:Key="ToolTipStyle">
<Setter Property="ToolTipService.ToolTip" Value="{StaticResource FooToolTip}"/>
<Setter Property="ToolTipService.PlacementTarget" Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}}"/>
</Style>
</Window.Resources>
<Grid>
<TextBlock
Text="Foo" Style="{StaticResource ToolTipStyle}"
HorizontalAlignment="Center" VerticalAlignment="Center" Height="20" Width="50">
</TextBlock>
</Grid>
</Window>
As for your second snippet in code behind, you can't set the PlacementTarget once the ToolTip is open and when the ToolTip is closed the PlacementTarget is null. As #mm8 pointed out, this has to do with the ToolTip and the PlacementTarget being in different visual trees, since a ToolTip spawns
a Window of its own.

Use Style in TreeView HierarchicalDataTemplate

I'm new to this and can't quit get the correct syntax. This works correctly to capture the Left Mouse click on the textbox within the treeview:
<HierarchicalDataTemplate
DataType="{x:Type r:NetworkViewModel}"
ItemsSource="{Binding Children}"
>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding NetworkIP}" Width="110" >
<TextBlock.InputBindings>
<MouseBinding MouseAction="LeftClick"
Command="{Binding DataContext.SelectItem, RelativeSource={RelativeSource FindAncestor, AncestorType=TreeView}}"
CommandParameter="{Binding}" />
</TextBlock.InputBindings>
</TextBlock>
</StackPanel>
</HierarchicalDataTemplate>
How can this be done using a Style block in the Resources?
The goal being to use the same style for all TextBoxes in the TreeView. Something that would sit in the Usercontrol.Resources and be refrenced by the HierarchicalDataTemplate.
If I understand you correctly, you could define a template in the controls or windows resources with a target type (opposed to key x:Key=...) to have it automatically applied to all items in the tree view.
Here is a small example with a definition of a template in the window resources, which contains the InputBindings definition. This template will be automatically applied to all objects of type ItemViewModel if no other template is explicitly defined by the ItemsControl or TreeView. In this example, the items are displayed in a simple ItemsControl but it works for the TreeView just the same.
Note that for this to work, all items in the TreeView need to be of the same type. It is not sufficient if they are derived from the same base type. The template will only be applied, if the type defined in Template.DataType is exactly the same as the type of the ViewModel. If your TreeViews ItemsScources contain mixed type, you would need to specify the template for every type separately.
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:loc="clr-namespace:WpfApplication2"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<DataTemplate DataType="{x:Type loc:ItemViewModel}">
<TextBlock Text="{Binding Name}" Width="110" >
<TextBlock.InputBindings>
<MouseBinding
MouseAction="LeftClick"
Command="{Binding SelectItem}" />
</TextBlock.InputBindings>
</TextBlock>
</DataTemplate>
</Window.Resources>
<Grid>
<ItemsControl ItemsSource="{Binding Items}" />
</Grid>
</Window>

binding combobox images - how to select saved item in combobox images

I have a Problem with the ComboBox at wpf and xaml. The ItemsSource of my combobox is a list of (CollarTypesImage).
the binding is work fine but the problem when editing data, i can't select the item of my ComboBox.. maybe its selected but the image is not view...
but when click ComboBox, i can see all itams:
http://www.ahmadabouhamdh.com/tmp_global/1.png
i used RelativeSource , nothing changed, ComboBox not selection the my saved item:
<UserControl x:Class="TailorManager.Views.OrderDetailItem"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:vm="clr-namespace:TailorManager.ViewModels"
xmlns:Converter="clr-namespace:TailorManager.Converters"
mc:Ignorable="d"
d:DesignHeight="730" d:DesignWidth="556" FlowDirection="RightToLeft" >
<UserControl.Resources>
<!--<vm:OrderDetailItemViewModel x:Key="OrderDetailItemViewModel1" />-->
<Converter:ImageConverter x:Key="ImgConverter" />
</UserControl.Resources>
<Grid >
<ScrollViewer VerticalScrollBarVisibility="Auto" >
<ItemsControl>
<StackPanel>
<GroupBox Header="تفاصيل الياقة" Margin="5,5,5,0" VerticalAlignment="Top" Height="170">
<Grid>
<ComboBox ItemsSource="{Binding Path= DataContext.ImagesCollarTypes,
RelativeSource={RelativeSource AncestorType=UserControl,AncestorLevel=1}}"
SelectedValue="{Binding Path=OrderDetailItem.CollarTypesImage,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
SelectedValuePath="{Binding Path=OrderDetailItem.CollarTypesImage}"
Margin="393,106,0,0" VerticalAlignment="Top" HorizontalAlignment="Left" Width="132" Height="38">
<ComboBox.ItemTemplate>
<DataTemplate>
<Image Width="50" Height="50" Source="{Binding Path= CollarImage,Converter={StaticResource ImgConverter} }" />
</DataTemplate>
</ComboBox.ItemTemplate >
</ComboBox>
</Grid>
</GroupBox>
<Grid/>
</StackPanel>
</ItemsControl>
</ScrollViewer>
</Grid>
</UserControl>
i added
SelectedItem="{Binding Path=OrderDetailItem.CollarTypesImage}"
and nothing changed.
i use this Control inside window has a different DataContext type,i set the value of (DataContext OrderDetailItem) from constructor of this control.
image below explain the binding is working fine:
this image when click edit to show my saved image from DB, my item not selected:
http://www.ahmadabouhamdh.com/tmp_global/2.png
here all the code:
public List<CollarTypesImage> ImagesCollarTypes
{
get
{
//ImagesCollarTypes[0].CollarImage
if (_imagesCollarTypes.Count == 0)
{
TailorManagerDBEntities db = new TailorManagerDBEntities();
_imagesCollarTypes = db.CollarTypesImages.ToList();
}
return _imagesCollarTypes;
}
set
{
_imagesCollarTypes = value;
RaisePropertyChanged(() => ImagesCollarTypes);
}
}
public partial class CollarTypesImage
{
public CollarTypesImage()
{
this.OrderDetails = new HashSet<OrderDetail>();
}
public System.Guid CollarTypeId { get; set; }
public byte[] CollarImage { get; set; }
public virtual ICollection<OrderDetail> OrderDetails { get; set; }
}
here the xaml code from window i used my control:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:TailorManager.ViewModels"
xmlns:util="clr-namespace:TailorManagerLib.Business;assembly=TailorManagerLib"
xmlns:local="clr-namespace:TailorManager.Views"
x:Class="TailorManager.Views.AddOrder"
Title="AddCustomer" Height="665" Width="974" MinWidth="600" MinHeight="666" FlowDirection="RightToLeft" >
<Window.Resources>
<vm:ManageOrderDetilsViewModel x:Key="ManageOrderDetilsViewModel1" />
</Window.Resources>
<Grid DataContext="{StaticResource ManageOrderDetilsViewModel1}" x:Name="GridDataContaner">
<Grid.Background>
...
</Grid.Background>
<GroupBox Header="تفاصيل الطلب" Margin="10,160,10,0" FlowDirection="RightToLeft">
<Grid Grid.Column="0" Name="GridOrderDetails">
<Grid.ColumnDefinitions>
<ColumnDefinition Name="ColumnDefinitionListDetails" Width="183*"/>
<ColumnDefinition Name="ColumnDefinitionDetails" Width="0*"/>
</Grid.ColumnDefinitions>
<Grid Margin="0,0,0,40" >
...
</Grid>
<Grid Grid.Column="1">
<Border BorderBrush="Black" BorderThickness="2" CornerRadius="3" Margin="4" >
<Grid>
<local:OrderDetailItem x:Name="OrderDetailItemControl" VerticalAlignment="Top" />
</Grid>
</Border>
</Grid>
...
</Grid>
</GroupBox>
</Grid>
</Window>
how i set the DataContext of the Control, this inside the command in VM of my window:
OrderDetailItemViewModel OrdDetailItem = new OrderDetailItemViewModel(Ord.OrderDetailsId);
OrderDetailItemControl.DataContext = OrdDetailItem;
Please how to fix it??
UPDATE
when i change the relative source as below:
<ComboBox Name="CmbBxImgCollarTyp" ItemsSource="{Binding Path= DataContext.ImagesCollarTypes, RelativeSource={
RelativeSource AncestorType={x:Type vm:OrderDetailItemViewModel}}"
SelectedValue="{Binding Path=OrderDetailItem.CollarTypesImage, Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}" SelectedValuePath="{Binding Path= OrderDetailItem.CollarTypesImage}" Margin="393,106,0,0" VerticalAlignment="Top"
HorizontalAlignment="Left" Width="132" Height="38">
<ComboBox.ItemTemplate>
<DataTemplate>
<Image Width="50" Height="50" Source="{Binding Path=CollarImage,
Converter={StaticResource ImgConverter}}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
the binding never work at all modes!, i change it to this way cause the datacontext of this control is an object of the viewmodel "OrderDetailItemViewModel"
What should be fix؟؟
You have an error in your RelativeSource Binding Path. You have used the type of UserControl, but the UserControl class does not have a property named ImagesCollarTypes... instead, you should use your UserControl where you defined the property... I'm assuming that class was named OrderDetailItem:
<ComboBox ItemsSource="{Binding Path= DataContext.ImagesCollarTypes, RelativeSource={
RelativeSource AncestorType={x:Type YourViewsPrefix:OrderDetailItem}}}"
SelectedValue="{Binding Path=CollarTypesImage, Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}" SelectedValuePath="{Binding Path=
CollarTypesImage}" Margin="393,106,0,0" VerticalAlignment="Top"
HorizontalAlignment="Left" Width="132" Height="38">
<ComboBox.ItemTemplate>
<DataTemplate>
<Image Width="50" Height="50" Source="{Binding Path=CollarImage,
Converter={StaticResource ImgConverter}}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
You should have received an error in the Output Window in Visual Studio saying something like Error: property 'ImagesCollarTypes' not found on object 'UserControl' or something similar.
Disclaimer: I didn't go through all of your code because you simply have too much there, so even after you fix this error, your code may still have other errors and not work as expected.
UPDATE >>>
For this Binding to work, the following assumptions were made:
The UserControl.DataContext must have a valid instance of an object set.
The object set as the UserControl.DataContext must have a public property named ImagesCollarTypes.
The ImagesCollarTypes property must be of a type that contains a public property named CollarTypesImage.
after check the Output window, i notes this error:
System.Windows.Data Error: 4 : Cannot find source for binding with
reference 'RelativeSource FindAncestor, AncestorType='Projectname.ViewModels.ViewModel', AncestorLevel='1''. BindingExpression:Path=LookupItems; DataItem=null; target element is 'ComboBox' (Name=''); target property is 'ItemsSource' (type 'IEnumerable')
then i change the RelativeSource from AncestorType from my ViewModel to UserControl, just like this:
RelativeSource={ AncestorType={x:Type UserControl},AncestorLevel=1}}"
and now everything working fine,
Thanks for members make an effort

Displaying Image in ComboBox's selected item

I have a custom template for my WPF windows ComboBoxes, which display items that inherit from ComboBoxItem that also have an Image property (so that my items can display both text and an image). Both the text and image display as expected in the ComboBox's popup menu for any given item, but I haven't been able to display an image in the currently selected item.
The ContentPresenter within the ComboBox template that displays the currently selected item has its Content property properly bound to {TemplateBinding SelectionBoxItem}, and its ContentTemplate is bound to the following static resource:
<DataTemplate x:Key="SelectionBoxItemTemplateTextAndImage" DataType="{x:Type SB:SBComboBoxItem}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Image Source="{Binding Image}"/>
<TextBlock Grid.Column="1" Text="{Binding}"/>
</Grid>
</DataTemplate>
SBComboBoxItem is the custom control that inherits from ComboBox and contains an "Image" property properly registered as a DependencyProperty.
I have attempted alternative implementations of that DataTemplate, including using:
{Binding Path=Image, RelativeSource={RelativeSource TemplatedParent}}
as the image's source. That didn't work, even though the text still displays when i set the TextBlock's Text property to:
{Binding Path=Content, RelativeSource={RelativeSource TemplatedParent}}
I've played around and found numerous implementations that display the text, but the equivalents never work for the image. I don't understand why this doesn't work, as setting up the popup to display both images and text was a breeze.
Edit: Here's the added functionality to ComboBoxItem to handle the image, in case there's something I did wrong there:
public static readonly DependencyProperty ImageProperty = DependencyProperty.Register("Image", typeof(Image), typeof(SBComboBoxItem));
public Image Image { get { return (Image)GetValue(ImageProperty); } set { SetValue(ImageProperty, value); } }
And here is where I have a ComboBox with the items added:
<ComboBox SelectedIndex="1">
<SB:SBComboBoxItem Content="Text">
<SB:SBComboBoxItem.Image>
<Image Source="..\Images\Table.png"/>
</SB:SBComboBoxItem.Image>
</SB:SBComboBoxItem>
<SB:SBComboBoxItem Content="MoreText">
<SB:SBComboBoxItem.Image>
<Image Source="..\Images\Euclidian.png"/>
</SB:SBComboBoxItem.Image>
</SB:SBComboBoxItem>
</ComboBox>
Despite the fact that I was using a DataTemplate to expose the underlying type of my selected combobox item through DataTemplate's DataType property, the SelectionBoxItem property of my ComboBox was apparently returning something that could not be cast as my custom ComboBoxItem. I don't know why this is, nor why it did not fire any runtime errors, but I found that by binding to ComboBox's SelectedItem property instead of SelectionBoxItem in the ContentPresenter allowed me to access user defined properties.
Does the DataTemplate even work? As far I remember, any WPF element that can be rendered, wont use a DataTemplate. And your custom ComboBoxItem can be rendered without the DataTemplate.
So the first question is, is the DataTemplate even applied? (Just change the background of DataTemplates' grid and find that out, if it works).
Let's assume the DataTemplate actually works, what I would try:
{Binding Path=Image, RelativeSource={RelativeSource AncestorType={x:Type SB:SBComboBoxItem}}
or RelativeSource as TemplatedParent with Content.Image
Okay, on the DataTemplate part, you have to bind against Image's Source property, not against Image itself.
Like so:
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<BitmapImage x:Key="validImg" UriSource="test.png" />
<DataTemplate x:Key="TEMP" DataType="ComboBoxItem">
<StackPanel Orientation="Horizontal">
<!--Not working Content(Image) is not valid for Source property I think-->
<Image Source="{Binding Path=Content}" />
<!--Working -->
<Image Source="{Binding Path=Content.Source}" />
<TextBlock Text="{Binding Path=Content}" />
</StackPanel>
</DataTemplate>
</Window.Resources>
<Grid>
<ContentPresenter
Content="{Binding Items[0], ElementName=test}"
ContentTemplate="{StaticResource TEMP}">
</ContentPresenter>
<ComboBox x:Name="test" Height="50" Margin="0, 50, 0, 0">
<ComboBoxItem >
<ComboBoxItem.Content>
<Image Source="{StaticResource validImg}" />
</ComboBoxItem.Content>
</ComboBoxItem>
</ComboBox>
</Grid>

WPF - Trouble binding ToolTip text on custom user control

I'm in the process of creating a simple user control; just an ImageButton.
I've already successfully bound the Image to the button and so I've decided to add a tooltip. Now I'm having troubles. It seems that I can hard-code the text for the tooltip in the XAML for the control, but when it's bound it's returning an empty string.
Here's the XAML for my control:
<Button x:Class="BCOCB.DACMS.Controls.ImageButton"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
Name="this"
Style="{StaticResource DisabledButton}">
<Image Source="{Binding ElementName=this, Path=Source}" />
<Button.ToolTip>
<TextBlock Text="{Binding ElementName=this, Path=ToolTipText}" />
</Button.ToolTip>
</Button>
And here's the dependency property info for the tooltip text:
public static readonly DependencyProperty ToolTipTextProperty = DependencyProperty.Register("ToolTipText", typeof(string), typeof(ImageButton));
public string ToolTipText
{
get
{
return this.GetValue(ToolTipTextProperty) as string;
}
set
{
this.SetValue(ToolTipTextProperty, value);
}
}
And, finally, the declaration of the control in my Window:
<controls:ImageButton x:Name="btnAdd" Source="/DACMS;component/Resources/plus.png" ToolTipText="Add New Item" Click="btnAdd_Click" />
As I mentioned before, the image binds just fine and I've done it in exactly the same manner.
Any ideas?
Thanks,
Sonny
EDIT: I have it working now. I've removed the ElementName from the binding and set the TextBlock's DataContext = this in the code behind on instanciation. Still, I'd like to know how to fix this in the XAML, instead.
I'm unable to test this right now, but you can try:
<Button.ToolTip
DataContext=”{Binding Path=PlacementTarget.Parent.Parent,
RelativeSource={x:Static RelativeSource.Self}}"
>
<TextBlock Text="{Binding Path=ToolTipText}" />
</Button.ToolTip>
You may have to experiment a little with the number of "Parent" in PlacementTarget.
Hopefully this works. I don't like giving answers that I haven't tested, but I don't have VS on this computer. :)
I've had this same problem with binding to a ContextMenu. After my research I think that it is because the ToolTip and ContextMenu do not exist within the visual tree of your page/window/control. And therefore the DataContext is not inherited and makes binding troublesome.
Here is a Xaml hack I found that worked for me.
Binding to a MenuItem in a WPF Context Menu
The way to set the data context to "this" through xaml looks like this:
<Control DataContext={Binding RelativeSource={RelativeSource Self}}>
As another point, wpf buttons allow their content to be just about any (single) thing you want. If you want something other than text (ie, text and an image), it looks like this:
<Button Name="SampleButton" Click="SampleButton_Click">
<Grid Width="70" Height="62">
<Label Content="SampleText"/>
<Image Margin="3,3,3,3" Source="Graphics/sample.ico"/>
</Grid>
</Button>
Since you aren't changing anything but the Text on the tooltip TextBlock you can just use an inline declaration which will generate the TextBlock for you and doesn't require any hacking to get around the name scoping issue you're running into otherwise:
<Button ... ToolTip="{Binding RelativeSource={RelativeSource Self}, Path=ToolTipText}">...
You could alternately set the ToolTip on the Image and use the control as the DataContext, which gets around the name scoping problem. The DataContext will be passed to the ToolTip, allowing normal binding:
<Image DataContext="{Binding ElementName=this}" Source="{Binding Source}">
<Image.ToolTip>
<TextBlock FontSize="18" Text="{Binding Path=ToolTipText}" />
</Image.ToolTip>
</Image>
This way allows additional settings on the TextBlock or more complex visuals.
This fixes the Problem with the Tooltip Bindings and Dependencies Properties:
<UserControl x:Class="Extended.InputControls.TextBoxUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Extended.InputControls"
x:Name="UserControl"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<TextBox x:Name="textBox">
<TextBox.ToolTip>
<ToolTip Content="{Binding Path=CustomToolTip}" Background="Yellow"/>
</TextBox.ToolTip>
</TextBox>
</UserControl>
Instead of this ( doesnt Work ):
<UserControl x:Class="Extended.InputControls.TextBoxUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Extended.InputControls"
x:Name="UserControl">
<TextBox x:Name="textBox">
<TextBox.ToolTip>
<ToolTip Content="{Binding ElementName=UserControl, Path=CustomToolTip}" Background="Yellow"/>
</TextBox.ToolTip>
</TextBox>
</UserControl>

Categories

Resources