eXPerience
eXPerience

Reputation: 466

Bind textBox's control text to class property

I have a diagram designer, in which every figure should have editable sign on it. This is how the programm looks like. enter image description here

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

Answers (1)

grek40
grek40

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

Related Questions