Show Ellipsis(...) Button When Text Exceeds Range WPF - c#

I have one TextBlock having width say 100. When the text length is a large one I want to show the characters that is accomodated in that textblock and a (...) button besides the text to specify user that more text is also there. Upon click on that (...) button, the full text will be shown in a separate pop up window.
So i want how the dynamic (...) button will be shown whenever the text length exceed the size of the textblock. Please answer

This isn't exactly what you want, but it's a similar idea and just uses the baked-in stuff:
<TextBlock MaxWidth="200"
Text="{Binding YourLongText}"
TextTrimming="WordEllipsis"
ToolTip="{Binding YourLongText}" />
So you have a TextBlock with a maximum width, and when the text can't fit it displays an ellipsis ("..."). Hovering over the TextBlock with your mouse will show the full text in a ToolTip.

Just experience the same requirement for adding ellipsis on button so adding the solution here
<Style x:Key="editButton" TargetType="{x:Type Button}">
<Setter Property="Background" Value="Transparent" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Left" VerticalAlignment="Center" >
<ContentPresenter.Resources>
<Style TargetType="TextBlock">
<Setter Property="TextTrimming" Value="CharacterEllipsis"></Setter>
</Style>
</ContentPresenter.Resources>
</ContentPresenter>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Transparent"/>
</Trigger>
</Style.Triggers>
</Style>
Notice the resources in content presenter.

I believe what you want is to set the TextTrimming property. Settng it to WordElilipsis or CharacterEllipsis should provide what you need.

My solution to the problem is probably overkill, but allows for some configuration and control.
I created a behavior that allows me to set the character limit for each binding.
internal class EllipsisStringBehavior
{
public static readonly DependencyProperty CharacterLimitDependencyProperty = DependencyProperty.RegisterAttached("CharacterLimit", typeof(int), typeof(EllipsisStringBehavior), new PropertyMetadata(255, null, OnCoerceCharacterLimit));
public static readonly DependencyProperty InputTextDependencyProperty = DependencyProperty.RegisterAttached("InputText", typeof(string), typeof(EllipsisStringBehavior), new PropertyMetadata(string.Empty, OnInputTextChanged));
// Input Text
public static string GetInputText(DependencyObject dependencyObject)
{
return Convert.ToString(dependencyObject.GetValue(InputTextDependencyProperty));
}
public static void SetInputText(DependencyObject dependencyObject, string inputText)
{
dependencyObject.SetValue(InputTextDependencyProperty, inputText);
}
// Character Limit
public static int GetCharacterLimit(DependencyObject dependencyObject)
{
return Convert.ToInt32(dependencyObject.GetValue(CharacterLimitDependencyProperty));
}
public static void SetCharacterLimit(DependencyObject dependencyObject, object characterLimit)
{
dependencyObject.SetValue(CharacterLimitDependencyProperty, characterLimit);
}
private static void OnInputTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
TextBlock textblock = (TextBlock)d;
string input = e.NewValue == null ? string.Empty : e.NewValue.ToString();
int limit = GetCharacterLimit(d);
string result = input;
if (input.Length > limit && input.Length != 0)
{
result = $"{input.Substring(0, limit)}...";
}
textblock.Text = result;
}
private static object OnCoerceCharacterLimit(DependencyObject d, object baseValue)
{
return baseValue;
}
}
I then simply add the using to my user control...
<UserControl
xmlns:behavior="clr-namespace:My_APP.Helper.Behavior"
d:DesignHeight="300" d:DesignWidth="300">
...and apply the behavior to the TextBlock control I wish to use it on.
<TextBlock Margin="0,8,0,8"
behavior:EllipsisStringBehavior.CharacterLimit="10"
behavior:EllipsisStringBehavior.InputText="{Binding Path=DataContext.FeedItemTwo.Body, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
Style="{StaticResource MaterialDesignSubheadingTextBlock}"
FontSize="14"/>
Hope this helps.

Related

WPF DataGrid seems to ignore IsTabStop setting, when pressing Enter

I have a datagrid with quite a few columns. Now normally user can press TAB to cycle between controls in the DataGrid cells. Data grid cells have been set to IsTabStop = false, so it's skipping focusing on the the cell itself and it just falls through until focus is given to an actual control.
This seems to NOT WORK if the user presses Enter because they want to work within that same column. DataGrid will pass the focus to the next cell in the COLUMN, BUT it will also ignore the IsTabStop setting, so it just gives focus to the cell itself not the control inside.
Any ideas how to fix this.
Short example
<DataGrid AutoGenerateColumns="False" Name="grid1" >
<DataGrid.Resources>
<Style TargetType="{x:Type Border}" x:Key="coloredBorder">
<Setter Property="Background" Value="Yellow"/>
</Style>
<Style TargetType="DataGridCell">
<Setter Property="IsTabStop" Value="False"/>
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding A, Mode=OneWay}" Header="A"/>
<DataGridTemplateColumn Header="B">
<DataGridTemplateColumn.CellStyle>
<Style TargetType="{x:Type DataGridCell}" BasedOn="{StaticResource {x:Type DataGridCell}}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridCell}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Border BorderBrush="Black" BorderThickness="0,0,1,0" Width="20" Height="20" Style="{DynamicResource coloredBorder}"/>
<ComboBox Grid.Column="1" SelectedItem="{Binding A, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
ItemsSource="{Binding MenuItems, ElementName=window}"></ComboBox>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</DataGridTemplateColumn.CellStyle>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
Also I have appended the example WPF app for this here. To reproduce, clck on one of the comboboxes to give it focus. Pres tab and you'll see that the next combo box gets focus normally. If I added more than one combo box column the combobox to the right would get focus.
BUT if you press enter, the focus would go to the cell below, but it won't then skip the cell and go for the cell content. Instead cell is highlighted.
Like so:
Based on reply I got on MSDN:
I solved this by making an attached property:
using System.Windows;
using System.Windows.Input;
namespace GridTabbing
{
public class EnterKeySample
{
public static bool GetIsEnabled(DependencyObject obj)
{
return (bool)obj.GetValue(IsEnabledProperty);
}
public static void SetIsEnabled(DependencyObject obj, bool value)
{
obj.SetValue(IsEnabledProperty, value);
}
static void ue_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
var ue = e.OriginalSource as FrameworkElement;
if (e.Key == Key.Enter)
{
e.Handled = true;
ue.MoveFocus(new TraversalRequest(FocusNavigationDirection.Down));
}
}
private static void ue_Unloaded(object sender, RoutedEventArgs e)
{
var ue = sender as FrameworkElement;
if (ue == null) return;
ue.Unloaded -= ue_Unloaded;
ue.PreviewKeyDown -= ue_PreviewKeyDown;
}
public static readonly DependencyProperty IsEnabledProperty =
DependencyProperty.RegisterAttached("IsEnabled", typeof(bool),
typeof(EnterKeySample), new UIPropertyMetadata(false, IsEnabledChanged));
static void IsEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var ue = d as FrameworkElement;
if (ue == null) return;
if ((bool)e.NewValue)
{
ue.Unloaded += ue_Unloaded;
ue.PreviewKeyDown += ue_PreviewKeyDown;
}
else
{
ue.PreviewKeyDown -= ue_PreviewKeyDown;
}
}
}
}
The weird bit is that the only thing this is doing is telling WPF to pass focus DOWN when user presses Enter, which I would have assumed was already happening but obviously isn't.

Getting binding expressions from code behind from Datatemplate Triggers

I've been set to maintain a wpf application where there is a listbox for logging purposes.
The items displayed using listbox are of type TextMessage, i.e. the listbox is bound to these text messages via
ObservableCollection<TextMessage> Messages;
listBox.DataContext = Messages;
Messages are then added with something like
Messages.Add(new TextMessage("Test", TypeOfMessage.Headline));
This is the definition of the class TextMessage
public enum TypeOfMessage
{
Normal,
Headline,
Focus,
Important,
Fail,
Success
}
public class TextMessage
{
public TextMessage(string content, TypeOfMessage typeOfMessage)
{
Content = content;
TypeOfMessage = typeOfMessage;
CreationTime = DateTime.Now;
}
public string Content { get; }
public TypeOfMessage TypeOfMessage { get; }
public DateTime CreationTime { get; }
}
The xaml definition for the listbox is something like this:
<ListBox x:Name="listBox" HorizontalAlignment="Left" Height="196" Margin="101,77,0,0" VerticalAlignment="Top" Width="256" ItemsSource="{Binding}" SelectionMode="Multiple">
<ListBox.InputBindings>
<KeyBinding
Key="C"
Modifiers="Control"
Command="Copy"
/>
</ListBox.InputBindings>
<ListBox.CommandBindings>
<CommandBinding
Command="Copy"
Executed="DoPerformCopy"
/>
</ListBox.CommandBindings>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock x:Name="TextToShow" Text="{Binding Content}"></TextBlock>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding TypeOfMessage}" Value="Normal">
<Setter TargetName="TextToShow" Property="Foreground" Value="Black"/>
</DataTrigger>
<DataTrigger Binding="{Binding TypeOfMessage}" Value="Focus">
<Setter TargetName="TextToShow" Property="Foreground" Value="Black"/>
<Setter TargetName="TextToShow" Property="FontWeight" Value="Bold"/>
</DataTrigger>
<DataTrigger Binding="{Binding TypeOfMessage}" Value="Headline">
<Setter TargetName="TextToShow" Property="Foreground" Value="RoyalBlue"/>
<Setter TargetName="TextToShow" Property="FontWeight" Value="Bold"/>
</DataTrigger>
<DataTrigger Binding="{Binding TypeOfMessage}" Value="Important">
<Setter TargetName="TextToShow" Property="Foreground" Value="Red"/>
</DataTrigger>
<DataTrigger Binding="{Binding TypeOfMessage}" Value="Fail">
<Setter TargetName="TextToShow" Property="Foreground" Value="Red"/>
<Setter TargetName="TextToShow" Property="FontWeight" Value="Bold"/>
</DataTrigger>
<DataTrigger Binding="{Binding TypeOfMessage}" Value="Success">
<Setter TargetName="TextToShow" Property="Foreground" Value="Green"/>
<Setter TargetName="TextToShow" Property="FontWeight" Value="Bold"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
This works nicely (i.e messages are displayed in the listbox in different font weight and color depending on their type), but now for the question :
Is there any way using BindingExpression or any other means to get the font formatting and coloring from code behind from the xaml definitions ?
The reason is that I want to just have the formatting in one place (just in the xaml as it is right now) but still be able to reuse it when I want to copy the contents (using code behind) including font formatting to the clipboard.
Example:
private void DoPerformCopy()
{
RichTextBox rtb = new RichTextBox();
foreach (TextMessage message in (listBox as ListBox)?.SelectedItems.Cast<TextMessage>().ToList())
{
TextPointer startPos = rtb.CaretPosition;
rtb.AppendText(message.Content);
rtb.Selection.Select(startPos, rtb.CaretPosition.DocumentEnd);
//
// Here it would be very nice to instead having multiple switch statements to get the formatting for the
// TypeOfMessage from the xaml file.
SolidColorBrush scb = new SolidColorBrush(message.TypeOfMessage == TypeOfMessage.Fail ? Colors.Red);
//
rtb.Selection.ApplyPropertyValue(RichTextBox.ForegroundProperty, scb);
}
// Now copy the whole thing to the Clipboard
rtb.Selection.Select(rtb.Document.ContentStart, rtb.Document.ContentEnd);
rtb.Copy();
}
Since I'm new to wpf, I'd really appreciate if someone has a tip for solving this. (I've tried hard to find an solution here at stackoverflow, but so far I've been unsuccessful)
Thanks in advance,
King regards
Magnus
Make a ContentPresenter with Content set to your TextMessage. Set the ContentTemplate to listBox.ItemTemplate and apply the template. It will create the visuals (TextBlock in this case). Then, just parse off the values from the TextBlock.
Also, your RichTextBox selection code wasn't working quite right so I fixed that by just inserting TextRanges to the end of it instead of trying to get the selection right.
private void DoPerformCopy(object sender, EventArgs e)
{
RichTextBox rtb = new RichTextBox();
foreach (TextMessage message in (listBox as ListBox)?.SelectedItems.Cast<TextMessage>().ToList())
{
ContentPresenter cp = new ContentPresenter();
cp.Content = message;
cp.ContentTemplate = listBox.ItemTemplate;
cp.ApplyTemplate();
var tb = VisualTreeHelper.GetChild(cp, 0) as TextBlock;
var fg = tb.Foreground;
var fw = tb.FontWeight;
var tr = new TextRange(rtb.Document.ContentEnd, rtb.Document.ContentEnd);
tr.Text = message.Content;
tr.ApplyPropertyValue(RichTextBox.ForegroundProperty, fg);
tr.ApplyPropertyValue(RichTextBox.FontWeightProperty, fw);
}
// Now copy the whole thing to the Clipboard
rtb.Selection.Select(rtb.Document.ContentStart, rtb.Document.ContentEnd);
rtb.Copy();
}

How to create wpf button class with four states that is similar to a checkbox [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
Using WPF and .net 4.5.
Was hoping someone could help me to create a 4 state button, functioning similar to a checkbox. Valid values to be: null, 0, 1 or 2.
The first three states are going to be the same graphic as a checkbox, the fourth will increase the border thickness.
I order to do this I need some help defining a new button class that cycles through these four states as it is clicked upon.
Here you go
I have created a control based on Button
XAML
<Button x:Class="CSharpWPF.StateButton"
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"
xmlns:l="clr-namespace:CSharpWPF">
<Button.Template>
<ControlTemplate TargetType="Button">
<Border x:Name="border"
Background="Transparent"
BorderThickness="1">
<CheckBox x:Name="check"
IsHitTestVisible="False"
Content="{TemplateBinding Content}" />
</Border>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding State, RelativeSource={RelativeSource Self}}"
Value="{x:Null}">
<Setter TargetName="check"
Property="IsChecked"
Value="{x:Null}" />
</DataTrigger>
<DataTrigger Binding="{Binding State, RelativeSource={RelativeSource Self}}"
Value="1">
<Setter TargetName="check"
Property="IsChecked"
Value="True" />
</DataTrigger>
<DataTrigger Binding="{Binding State, RelativeSource={RelativeSource Self}}"
Value="2">
<Setter TargetName="check"
Property="IsChecked"
Value="True" />
<Setter TargetName="border"
Property="BorderBrush"
Value="Blue" />
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
I've used triggers to control the visual appreance
code behind
namespace CSharpWPF
{
/// <summary>
/// Interaction logic for StateButton.xaml
/// </summary>
public partial class StateButton : Button
{
public StateButton()
{
InitializeComponent();
Click += (s, e) => ToggleState();
}
void ToggleState()
{
int? curState = State;
if (curState == null)
curState = 0;
else
curState++;
if (curState > 2)
curState = null;
State = curState;
}
public int? State
{
get { return (int?)GetValue(StateProperty); }
set { SetValue(StateProperty, value); }
}
// Using a DependencyProperty as the backing store for State. This enables animation, styling, binding, etc...
public static readonly DependencyProperty StateProperty =
DependencyProperty.Register("State", typeof(int?), typeof(StateButton), new PropertyMetadata(null), OnValidateState);
private static bool OnValidateState(object value)
{
if (value == null)
return true;
int parseResult = 0;
if (int.TryParse(Convert.ToString(value), out parseResult))
{
if (parseResult >= 0 && parseResult < 3)
return true;
}
return false;
}
}
}
you can customize your own state, currently null, 0, 1, 2. I suggest you to use an enum instead.

Styles and bindings acting oddly

Right. I've got a small program (that replicates my issue). Basically, it tries to bind to some properties of the object it's styling. It kind of works: it gives me the default value (from the dependency property). I've been thinking this may be because the Style's RelativeSource Self isn't the same as the TextBox it's styling's one. But I don't know. I've tried debugging this, checking time and again that the value set in XAML was actually set. The thing is, with a smaller test program it works. This is just a scale up from that. I don't know what's going wrong.
Thanks!
The code for reproducing this issue:
MainWindow.xaml
<Window x:Class="MyNamespace.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:lcl="clr-namespace:MyNamespace"
Title="My title." Height="350" Width="425" MaxHeight="350" MaxWidth="425" MinHeight="350" MinWidth="425">
<Window.Resources>
<ResourceDictionary Source="TestDictionary.xaml"/>
</Window.Resources>
<Grid>
<TextBox Style="{StaticResource TextBoxWithDefault}" FontSize="36" lcl:MyOptions.Default="Not default." VerticalAlignment="Center"/>
</Grid>
</Window>
MainWindow.xaml.cs
using System.Windows;
namespace MyNamespace
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
public static class MyOptions
{
public static string GetDefault(DependencyObject obj)
{
return (string)obj.GetValue(DefaultProperty);
}
public static void SetDefault(DependencyObject obj, string value)
{
obj.SetValue(DefaultProperty, value);
}
public static readonly DependencyProperty DefaultProperty =
DependencyProperty.RegisterAttached(
"Default",
typeof(string),
typeof(MyOptions),
new PropertyMetadata("Default"));
}
}
TestDictionary.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:lcl="clr-namespace:MyNamespace"
xmlns:sys="clr-namespace:System;assembly=mscorlib">
<Style TargetType="TextBox" x:Key="TextBoxWithDefault">
<Style.Resources>
<Label Content="{Binding Path=(lcl:MyOptions.Default), Mode=TwoWay, RelativeSource={RelativeSource Self}}"
Foreground="LightGray"
FontSize="{Binding Path=(FontSize), Mode=TwoWay, RelativeSource={RelativeSource Self}}" x:Key="TheLabel"/>
</Style.Resources>
<Style.Triggers>
<Trigger Property="Text" Value="{x:Static sys:String.Empty}">
<Setter Property="Background">
<Setter.Value>
<VisualBrush AlignmentX="Left" AlignmentY="Center" Stretch="None" Visual="{DynamicResource TheLabel}"/>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="Text" Value="{x:Null}">
<Setter Property="Background">
<Setter.Value>
<VisualBrush AlignmentX="Left" AlignmentY="Center" Stretch="None" Visual="{DynamicResource TheLabel}"/>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="True">
<Setter Property="Background" Value="White"/>
</Trigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
I have no idea what's going wrong here, as a scaled down version of this works perfectly. There's probably something I overlooked, that will seem pretty obvious when I find it. But I can't find it now.
EDIT: Well, it seems I was dumb. The original version (here) uses a Trigger, which means that it gets the parent textbox's value. The question now is: how can I get it working?
Thanks for your time!
The real show-stopper here is that when you use the Label in a VisualBrush, the label isn't part of the TextBox' "Visual Tree" (see for example Sheldon Xiao's answer to this similar question on MSDN: Binding Problem inside VisualBrush).
This means that the label won't inherit the text box' DataContext, and you can't reach the text box from a RelativeSource binding either. In contrast, the accepted answer in your other post sets the actual content of a button, which does make the content part of the button's visual tree.
So I don't think there's a pure XAML solution to this problem - pushing the correct MyOptions.Default from the text box to the label. One possible code-based solution is to scrap the TextBoxWithDefault style and do everything from your attached property when Default changes:
...
public static readonly DependencyProperty DefaultProperty =
DependencyProperty.RegisterAttached(
"Default",
typeof(string),
typeof(MyOptions),
//Listen for changes in "Default":
new PropertyMetadata(null, OnMyDefaultChanged));
private static void OnMyDefaultChanged(DependencyObject sender,
DependencyPropertyChangedEventArgs e)
{
var text = (TextBox)sender;
var myDefault = e.NewValue;
var defaultLabel = new Label();
defaultLabel.Foreground = Brushes.LightGray;
//Explicitly bind the needed value from the TextBox:
defaultLabel.SetBinding(Label.ContentProperty,
new Binding()
{
Source = text,
Path = new PropertyPath(MyOptions.DefaultProperty)
});
text.Background = new VisualBrush()
{
Visual = defaultLabel,
AlignmentX = AlignmentX.Left,
AlignmentY = AlignmentY.Center,
Stretch = Stretch.None
};
text.TextChanged += new TextChangedEventHandler(OnTextWithDefaultChanged);
}
private static void OnTextWithDefaultChanged(object sender,
TextChangedEventArgs e)
{
var text = (TextBox)sender;
var defaultLabel = (text.Background as VisualBrush).Visual as Label;
defaultLabel.Visibility = string.IsNullOrEmpty(text.Text) ?
Visibility.Visible :
Visibility.Collapsed;
}

Separate text in a Textbox with a drawn line?

So here it goes, I making a c# project in wpf and im stuck at trying to make a text box with a line that separates text.
At the moment i got the textbox like this:
Instead of using "-------" i want to make a predefined line in the textbox. Is this possible ?
Agg. The textbox is editable in runtime
The drawn line should have the properties:
It should not be edit able !
It shouldn't only be an empty line
It should be a visible line that has the width line.width = box.width !
If you don't need a full textbox implementation then this might help. It's got real issues with not showing the cursor ect but might give you a start.
first add the following converter to your project.
public class TextLineConverter : MarkupExtension, IValueConverter
{
static TextLineConverter converter;
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
string[] results = null;
string newText = value as string;
if (newText != null)
{
results = newText.Split('\r');
if (results.Length > 0)
for (int i = 0; i < results.Length; i++)
if (results[i].Length > 0)
if (results[i][0] == '\n')
results[i] = results[i].Substring(1, results[i].Length - 1);
}
return results;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
if (converter == null) converter = new TextLineConverter();
return converter;
}
public TextLineConverter()
{
}
}
And the following style.
<Style TargetType="TextBox">
<Style.Resources>
<Style TargetType="ListViewItem">
<Setter Property="Margin" Value="0"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="IsEnabled" Value="False"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border BorderThickness="0,0,0,2" BorderBrush="Black" >
<ContentPresenter Content="{Binding}" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Style.Resources>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<ListView Focusable="False" ItemsSource="{Binding Text, Converter={local:TextLineConverter}, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource TemplatedParent}}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
On rereading your question, i believe that the best way to do what you want is to create your own user-control that has an attribute specifically for this. Do some research on C# User Controls and perhaps you'll find out how to do this.

Categories

Resources