Reputation: 466
I have a diagram designer, in which every figure should have editable sign on it. This is how the programm looks like.
As you can see, the textbox with default text appears, but I cant figure out how to save the text input to corresponding "Text" property of DesignerItem class object. DesignerItem.xaml as follows:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:s="clr-namespace:WPFCanvas"
xmlns:c="clr-namespace:WPFCanvas.Controls">
<ContextMenu x:Key="DesignerItemContextMenu">
...
</ContextMenu>
<!-- Connector Style -->
<Style TargetType="{x:Type s:Connector}">
...
</Style>
<!-- ConnectorDecoratorTemplate Default Template -->
<ControlTemplate x:Key="ConnectorDecoratorTemplate" TargetType="{x:Type Control}">
...
</ControlTemplate>
<!-- ResizeDecorator Default Template -->
<ControlTemplate x:Key="ResizeDecoratorTemplate" TargetType="{x:Type Control}">
...
</ControlTemplate>
<!-- DragThumb Default Template -->
<Style TargetType="{x:Type c:DragThumb}">
...
</Style>
<!-- TextBoxDecorator Default Template -->
<ControlTemplate x:Key="TextBoxDecoratorTemplate" TargetType="{x:Type Control}">
<ContentControl Width="Auto" Height="Auto" VerticalAlignment="Center" HorizontalAlignment="Center">
<TextBox FontSize="11" Margin="1,1,0,0" TextWrapping="Wrap" AcceptsReturn="True"
Background="Transparent" Text="Lorem ipsum dolor sit amet, consectetuer adipiscing elit."/>
</ContentControl>
</ControlTemplate>
<!-- DesignerItem Style -->
<Style TargetType="{x:Type s:DesignerItem}">
<Setter Property="MinWidth" Value="25"/>
<Setter Property="MinHeight" Value="25"/>
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type s:DesignerItem}">
<Grid DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}"
ContextMenu="{StaticResource DesignerItemContextMenu}">
<!-- DragThumb -->
<c:DragThumb x:Name="DragThumb" Cursor="SizeAll"/>
<!-- ResizeDecorator -->
<Control x:Name="ResizeDecorator"
Visibility="Collapsed"
Template="{StaticResource ResizeDecoratorTemplate}"/>
<!-- ContentPresenter -->
<ContentPresenter x:Name="ContentPresenter"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Content="{TemplateBinding ContentControl.Content}"
Margin="{TemplateBinding ContentControl.Padding}"/>
<!-- ConnectorDecorator -->
<Control x:Name="ConnectorDecorator"
Visibility="Hidden"
Template="{StaticResource ConnectorDecoratorTemplate}"/>
<!-- TextBoxDecorator -->
<Control x:Name="TextBoxDecorator"
Template="{StaticResource TextBoxDecoratorTemplate}"/>
</Grid>
<ControlTemplate.Triggers>
<DataTrigger Value="True" Binding="{Binding RelativeSource={RelativeSource Self},Path=Text}">
<Setter TargetName="TextBoxDecorator" Property="Visibility" Value="Visible"/>
</DataTrigger>
<Trigger Property="Text" Value="true">
<Setter TargetName="TextBoxDecorator" Property="Visibility" Value="Visible"/>
</Trigger>
<DataTrigger Value="True" Binding="{Binding RelativeSource={RelativeSource Self},Path=IsSelected}">
<Setter TargetName="ResizeDecorator" Property="Visibility" Value="Visible"/>
</DataTrigger>
<Trigger Property="IsMouseOver" Value="true">
<Setter TargetName="ConnectorDecorator" Property="Visibility" Value="Visible"/>
</Trigger>
<DataTrigger Value="True" Binding="{Binding RelativeSource={RelativeSource Self},Path=IsDragConnectionOver}">
<Setter TargetName="ConnectorDecorator" Property="Visibility" Value="Visible"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And the DesignerItem.cs (without unnecessary code as well):
//These attributes identify the types of the named parts that are used for templating
[TemplatePart(Name = "DragThumb", Type = typeof(DragThumb))]
[TemplatePart(Name = "ResizeDecorator", Type = typeof(Control))]
[TemplatePart(Name = "ConnectorDecorator", Type = typeof(Control))]
[TemplatePart(Name = "ContentPresenter", Type = typeof(ContentPresenter))]
public class DesignerItem : ContentControl, ISelectable, IGroupable
{
public bool IsSelected
{
get { return (bool)GetValue(IsSelectedProperty); }
set { SetValue(IsSelectedProperty, value); }
}
public static readonly DependencyProperty IsSelectedProperty =
DependencyProperty.Register("IsSelected", typeof(bool),
typeof(DesignerItem),
new FrameworkPropertyMetadata(false));
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(string),
typeof(DesignerItem));
}
Upvotes: 1
Views: 334
Reputation: 13448
In order to save the text from the visual TextBox
to the DesignerItem.Text
property, a Binding
is needed. The binding target is the TextBox
inside the TextBoxDecoratorTemplate
and the binding source is the DesignerItem.Text
property.
Since you assign the DesignerItem
instance as your DataContext
(<Grid DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}" .../>
), the binding can directly target the Text
property of the DataContext
contents.
<!-- TextBoxDecorator Default Template -->
<ControlTemplate x:Key="TextBoxDecoratorTemplate" TargetType="{x:Type Control}">
<ContentControl Width="Auto" Height="Auto" VerticalAlignment="Center" HorizontalAlignment="Center">
<TextBox FontSize="11" Margin="1,1,0,0" TextWrapping="Wrap" AcceptsReturn="True"
Background="Transparent" Text="{Binding Text}"/>
</ContentControl>
</ControlTemplate>
A little side note:
Your ControlTemplate.Triggers
look like they need some changes. You are triggering a string property against Value="True"
, which will only trigger when the text contains the string "True"
. I feel like the idea was more like triggering on something else.
Upvotes: 1