I am using the following code to move the text in TextBlock from right to left:-
ThicknessAnimation ThickAnimation = new ThicknessAnimation();
ThickAnimation.From = new Thickness(0, 0, 0, 0);
ThickAnimation.To = new Thickness(-TextGraphicalWidth, 0, 0, 0);
ThickAnimation.RepeatBehavior = RepeatBehavior.Forever;
ThickAnimation.Duration = new Duration(TimeSpan.FromSeconds(40);
TextBlockMarquee.BeginAnimation(TextBlock.MarginProperty, ThickAnimation);
The problem I am having is this code works perfectly for a text whose width is less then that of screen. But for text whose width is greater then screen the text flickers a lot(Flickering increases when text contains unicode characters like: "\u25Bc").
here:-
TextGraphicalWidth is width of original text.
TextLenghtGraphicalWidth is width of text after appending text to original text.
How can I handle this?
Xaml:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Canvas ClipToBounds="True" Name="canMain" Background="Transparent">
<Grid Width="{Binding ElementName=canMain, Path=ActualWidth}" >
<Grid.ColumnDefinitions>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Name="TextBlockMarquee" Text="This is my animated text with special characters:" />
<Border Grid.Row="1" BorderBrush="Black" BorderThickness="1">
<TextBlock ClipToBounds="True" FontSize="22" Name="TextBoxMarquee" FontFamily="Segoe UI" Text="" />
</Border>
<TextBlock Grid.Row="2" Name="TextBlockMarqueenew" Text="This is my animated text without special characters:" />
<Border Grid.Row="3" BorderBrush="Black" BorderThickness="1">
<TextBlock ClipToBounds="True" FontSize="22" Name="TextBoxMarquee1" FontFamily="Segoe UI" Text="" />
</Border>
</Grid>
</Canvas>
</Grid>
Code Behind:-
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace TickerDemoNew
{
/// <summary>
/// Interaction logic for TickerMaxTextBlock.xaml
/// </summary>
public partial class TickerMaxTextBlock : Window
{
StringBuilder s,s1;
string TexttoScroll, TexttoScroll1;
public TickerMaxTextBlock()
{
InitializeComponent();
TextOptions.SetTextFormattingMode(TextBoxMarquee,TextFormattingMode.Ideal);
UseLayoutRounding = true;
TextBoxMarquee.Inlines.Add(new Run("I have attached herewith the full implementation of Custom TextBox class (TextBoxEx) in a word file. In the implementation when Tooltip is opening, it is checking whether text has truncated or not. If text has not truncated then tooltip won’t be displayed (as it is not necessary because full text is anyway visible). Also, in order to show the tooltip, text property of the Textblock should be bound with the tooltip. ") { Foreground = Brushes.Red });
TextBoxMarquee.Inlines.Add(new Run(" Despite of all the interop support available sometimes you will still come across some tricky issues which will be difficult to overcome. One such problem I faced recently. I had to configure the Dialog with MFC PropertySheet control. This PropertySheet control was holding few Property pages. These property pages didn’t had any MFC controls as content but hosting the user controls developed in WPF. First I will write very briefly about how to load the WPF user control inside the MFC container and then I will explain about my tricky problem and how I fixed it.") { Foreground = Brushes.Green });
}
private void Window_Loaded_1(object sender, RoutedEventArgs e)
{
double TextGraphicalWidth = 0;
foreach (var str in TextBoxMarquee.Inlines)
{
TextGraphicalWidth = TextGraphicalWidth + new FormattedText(((Run)str).Text, System.Threading.Thread.CurrentThread.CurrentCulture, System.Windows.FlowDirection.LeftToRight, new Typeface(str.FontFamily.ToString()), str.FontSize, str.Foreground).WidthIncludingTrailingWhitespace;
}
double TextLenghtGraphicalWidth = 0;
while (TextLenghtGraphicalWidth < TextBoxMarquee.ActualWidth)
{
TextBoxMarquee.Inlines.Add(new Run("I have attached herewith the full implementation of Custom TextBox class (TextBoxEx) in a word file. In the implementation when Tooltip is opening, it is checking whether text has truncated or not. If text has not truncated then tooltip won’t be displayed (as it is not necessary because full text is anyway visible). Also, in order to show the tooltip, text property of the Textblock should be bound with the tooltip. ") { Foreground = Brushes.Red });
TextBoxMarquee.Inlines.Add(new Run(" Despite of all the interop support available sometimes you will still come across some tricky issues which will be difficult to overcome. One such problem I faced recently. I had to configure the Dialog with MFC PropertySheet control. This PropertySheet control was holding few Property pages. These property pages didn’t had any MFC controls as content but hosting the user controls developed in WPF. First I will write very briefly about how to load the WPF user control inside the MFC container and then I will explain about my tricky problem and how I fixed it.") { Foreground = Brushes.Green });
foreach (var str in TextBoxMarquee.Inlines)
{
TextLenghtGraphicalWidth = TextLenghtGraphicalWidth + new FormattedText(((Run)str).Text, System.Threading.Thread.CurrentThread.CurrentCulture, System.Windows.FlowDirection.LeftToRight, new Typeface(str.FontFamily.ToString()), str.FontSize, str.Foreground).WidthIncludingTrailingWhitespace;
}
}
TextBoxMarquee.Inlines.Add(new Run("I have attached herewith the full implementation of Custom TextBox class (TextBoxEx) in a word file. In the implementation when Tooltip is opening, it is checking whether text has truncated or not. If text has not truncated then tooltip won’t be displayed (as it is not necessary because full text is anyway visible). Also, in order to show the tooltip, text property of the Textblock should be bound with the tooltip. ") { Foreground = Brushes.Red });
TextBoxMarquee.Inlines.Add(new Run(" Despite of all the interop support available sometimes you will still come across some tricky issues which will be difficult to overcome. One such problem I faced recently. I had to configure the Dialog with MFC PropertySheet control. This PropertySheet control was holding few Property pages. These property pages didn’t had any MFC controls as content but hosting the user controls developed in WPF. First I will write very briefly about how to load the WPF user control inside the MFC container and then I will explain about my tricky problem and how I fixed it.") { Foreground = Brushes.Green });
double totalWidth = 0;
foreach (var newStr in TextBoxMarquee.Inlines)
{
totalWidth = totalWidth + new FormattedText(((Run)newStr).Text, System.Threading.Thread.CurrentThread.CurrentCulture, System.Windows.FlowDirection.LeftToRight, new Typeface(newStr.FontFamily.ToString()), newStr.FontSize, newStr.Foreground).WidthIncludingTrailingWhitespace;
}
MessageBox.Show((TextLenghtGraphicalWidth + TextBoxMarquee.ActualWidth).ToString());
MessageBox.Show((TextLenghtGraphicalWidth + TextGraphicalWidth).ToString());
MessageBox.Show(totalWidth.ToString());
ThicknessAnimation ThickAnimation = new ThicknessAnimation();
ThickAnimation.From = new Thickness(0, 0, 0, 0);
ThickAnimation.To = new Thickness(-TextGraphicalWidth, 0, 0, 0);
ThickAnimation.RepeatBehavior = RepeatBehavior.Forever;
ThickAnimation.Duration = new Duration(TimeSpan.FromSeconds((50 * (totalWidth)) / TextBoxMarquee.ActualWidth));
TextBoxMarquee.BeginAnimation(TextBlock.MarginProperty, ThickAnimation);
}
}
}
Related
I have a situation where I need to create View box with one button. The xaml for this is as below: Please observe Width property of viewbox. The Width should be increased/decreased according to a slider bar(moving to right increases it, to left decreases it). As listed below I know how to do it in xaml and it works fine. But my requirement is to be able to create viewbox in code behind and assign it the properties.
<WrapPanel x:Name="_wrpImageButtons" Grid.IsSharedSizeScope="True"
ScrollViewer.CanContentScroll="True" d:LayoutOverrides="Height"
Margin="5">
<Viewbox x:Name="_ScaleButton"
Width="{Binding Value, ElementName=ZoomSlider}" Stretch="Fill">
<CustomButton:_uscVCARSImagesButton x:Name="_btnImage1"/>
</Viewbox>
</WrapPanel>
Thanks.
This should do what you want:
Viewbox x = new Viewbox();
Binding bnd = new Binding("Value") { ElementName = "ZoomSlider"};
BindingOperations.SetBinding(x, Viewbox.WidthProperty, bnd);
// ... Code to insert the Viewbox into the WrapPanel etc.
You can create the binding relatively easily in Code Behind:
var widthBinding = new Binding("Value") { ElementName = "ZoomSlider" };
_ScaleButton.SetBinding(FrameworkElement.WidthProperty, widthBinding);
I have used WPF to develop two moderately sized applications. I was much impressed by the cleanness of WPF and its features. When I explained to one of my colleagues (Who happens to develop business apps) the various benefits of WPF, he challenged me with this problem which had me totally stumped:
The Problem:
He coded an application in the following way in about 2 minutes:
Open a new WinForms project.
Define a class Loan.
Build project.
Define an object data source using Loan.
In Data Sources explorer, change view type of the Loan data source to Details.
Drag the data source onto the Form in the designer.
Supply the data source with a Loan[] containing one object.
Build and run application.
The code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WinForms_DataBinding_Example
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
loanBindingSource.DataSource = new Loan[] { new Loan() };
}
}
public class Loan
{
public decimal Amount { get; set; }
public decimal Rate { get; set; }
public decimal Total { get { return Amount * Rate; } }
}
}
The designer:
The application:
Now whenever you change the value of Amount or Rate in the window, the value of Total changes accordingly. After explaining that this is a very useful feature in business apps where any changes you make to one property in an entity immediately updates the view where calculated properties are refreshed instantly making the user experience better. Considering that the typical business entity class has a lot of properties, this saves a lot of coding. Then he asked me to do the same in WPF.
I first explained to him that I do not understand what sort of black magic goes on here. How does the Total textbox update itself automatically? This is my first question:
Q1. The Loan class does not implement INotifyPropertyChanged or something similar. So how does the Total textbox get updated when the Amount or Rate textboxes lose focus?
Then I told him that I do not know how to do the same thing so easily in WPF. However, I wrote the same app in WPF with 3 TextBlocks and 3 TextBoxs in the UI. I also needed to make Loan class implement INotifyPropertyChanged. Added backing fields to Amount and Rate. Whenever these properties were being set, I raised a property changed notification for the property Total. In the end, I was left with an app with badly aligned controls which did the same thing as the WinForms app. However, this was way harder to do than the WinForms method.
I came home and then had the bright idea of drag-dropping the Loan data source on to the WPF window (After I changed the view mode to detail). Sure enough, I got the same kind of UI as in WinForms app and after setting the data source to the same Loan[] as in WinForms app, it seemed to be complete. I ran the app, changed the Amount and Rate fields hoping to see Total change itself automagically. However, I was disappointed. The Total field did not change:
The code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using WinForms_DataBinding_Example;
namespace WPF_Grid_Example
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded_1(object sender, RoutedEventArgs e)
{
System.Windows.Data.CollectionViewSource loanViewSource = ((System.Windows.Data.CollectionViewSource)(this.FindResource("loanViewSource")));
// Load data by setting the CollectionViewSource.Source property:
loanViewSource.Source = new List<Loan>() { new Loan() };
}
}
}
The xaml:
<Window
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" xmlns:WinForms_DataBinding_Example="clr-namespace:WinForms_DataBinding_Example;assembly=WinForms_DataBinding_Example" mc:Ignorable="d" x:Class="WPF_Grid_Example.MainWindow"
Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded_1">
<Window.Resources>
<CollectionViewSource x:Key="loanViewSource" d:DesignSource="{d:DesignInstance {x:Type WinForms_DataBinding_Example:Loan}, CreateList=True}"/>
</Window.Resources>
<Grid>
<Grid x:Name="grid1" DataContext="{StaticResource loanViewSource}" HorizontalAlignment="Left" Margin="121,123,0,0" VerticalAlignment="Top">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Label Content="Amount:" Grid.Column="0" HorizontalAlignment="Left" Margin="3" Grid.Row="0" VerticalAlignment="Center"/>
<TextBox x:Name="amountTextBox" Grid.Column="1" HorizontalAlignment="Left" Height="23" Margin="3" Grid.Row="0" Text="{Binding Amount, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}" VerticalAlignment="Center" Width="120"/>
<Label Content="Rate:" Grid.Column="0" HorizontalAlignment="Left" Margin="3" Grid.Row="1" VerticalAlignment="Center"/>
<TextBox x:Name="rateTextBox" Grid.Column="1" HorizontalAlignment="Left" Height="23" Margin="3" Grid.Row="1" Text="{Binding Rate, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}" VerticalAlignment="Center" Width="120"/>
<Label Content="Total:" Grid.Column="0" HorizontalAlignment="Left" Margin="3" Grid.Row="2" VerticalAlignment="Center"/>
<TextBox x:Name="totalTextBox" Grid.Column="1" HorizontalAlignment="Left" Height="23" Margin="3" Grid.Row="2" Text="{Binding Total, Mode=OneWay}" VerticalAlignment="Center" Width="120"/>
</Grid>
</Grid>
</Window>
Q2. I was confounded before by the black magic of WinForms, I was confounded now because the same black magic did not work in WPF. Why?
Q3. How do I make the WPF version to update the Total field automatically as in the WinForms example?
Q4. Which platform is better/faster for this sort of business app development? If I am to make a better argument on behalf of WPF, what should I be looking at?
I hope I was clear about the problem. Please let me know if any clarifications are needed. Thanks.
Q1: If you look at the designer file for the Windows Form you'll see about 300 lines of code generated for your 3 textboxes. Some of this code is similar to:
this.amountTextBox.DataBindings.Add(
new System.Windows.Forms.Binding("Text",
this.loanBindingSource, "Amount", true));
The Binding and the BindingSource co-operate to update the bound values and cause all bound controls to be updated every time one of the values changes (using reflection).
Q2: Because the WPF designer doesn't create a .Designer.cs file and the associated mess of code. You need to explicitly implement INotifyPropertyChange, which can be simplified by using say MVVM Light's ViewModelBase, e.g.
public class Loan : ViewModelBase
{
public decimal Amount
{
get
{
return this.amount;
}
set
{
if (Set(() => Amount, ref this.amount, value))
{
RaisePropertyChanged(() => Total);
}
}
}
Q3:
1) When Amount or Rate changes raise the property change notification for that property but also for the computed property 'Total'.
2) Modify your bindings on Amount and Rate to Binding="{Binding Amount, UpdateSourceTrigger=LostFocus}"
Q4: WPF no question (IMHO). The WPF way is more testable and maintainable and understandable.
Answer to Q4:
Regardless of winforms having the ability to generate 3 silly textboxes for a class, WPF is a much better, scalable and powerful framework. It has much greater performance due to hardware acceleration and whatnot, and requires less or no code to do some tasks that take tons of code in winforms, such as this, or this:
<CheckBox x:Name="chk"/>
<TextBox IsEnabled="{Binding IsChecked,ElementName=chk}"/>
Also, tipical Line-of-Business applications have to deal with thousands or hundreds of thousands of records, and UI Virtualization makes a huge difference.
The bottom line is that winforms, regardless of having some designer goodies (which are more a feature of Visual Studio than winforms itself), is nowhere near as practical and adequate when it comes to Line of Business.
I have:
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<sdk:DataGrid Grid.Row="0" ...>
...
</sdk:DataGrid>
</Grid>
Note there is no Height="Auto" in row definition so that datagrid takes all height.
I'm trying to make a picture of full datagrid (include invisible space that needs scrolling). I tried:
ImageExtensions.ToImage(myDataGrid);
also
var writeableBitmap = new WriteableBitmap(pixelWidth, pixelHeight);
where pixelHeight was obtained either using SizeChanged event or DesiredSize property.
All in vain. Height was always the height of screen. If I used auto="height" in row definition then it would work, but datagrid wouldn't take all space / or no scroller when it's too large.
Anyone managed to get it work?
A workaround:
GridLength h = grid.RowDefinitions[0].Height;
grid.RowDefinitions[0].Height = GridLength.Auto;
grid.UpdateLayout();
try
{
var writeableBitmap = new WriteableBitmap((int)myDataGrid.ActualWidth, (int)myDataGrid.ActualHeight);
}
finally
{
grid.RowDefinitions[0].Height = h;
grid.UpdateLayout();
}
I have a FlowDocument which I want to fill the entire width and height of my window. I have tried using the FlowDocumentPageViewer (no luck) and am now using a DocumentPageView. I still can't get it to dock/fill the entire space; it's just sitting in the middle, in the minimum size it can create (does it make sense?)
Here is my code:
public DocumentPageView GetPage()
{
FlowDocumentPageViewer viewer = new FlowDocumentPageViewer();
StreamReader reader = new StreamReader(location);
string data = reader.ReadToEnd();
reader.Close();
string xamlData = HtmlToXamlConverter.ConvertHtmlToXaml(data, true);
FlowDocument result = (FlowDocument)System.Windows.Markup.XamlReader.Load(new MemoryStream(System.Text.UnicodeEncoding.Default.GetBytes(xamlData)));
viewer.Document = result;
viewer.VerticalAlignment = VerticalAlignment.Center;
viewer.HorizontalAlignment = HorizontalAlignment.Center;
DocumentPageView pageView = new DocumentPageView();
pageView.VerticalAlignment = VerticalAlignment.Center;
pageView.HorizontalAlignment = HorizontalAlignment.Center;
pageView.Stretch = System.Windows.Media.Stretch.Uniform;
pageView.PageNumber = 0;
pageView.StretchDirection = StretchDirection.Both;
pageView.DocumentPaginator = ((IDocumentPaginatorSource)result).DocumentPaginator;
return pageView;
}
Please note that this code contains the combination of my two methods but only the DocumentPageView is currently used. This is the Xaml that is created from my HTML source:
<FlowDocument xml:space="preserve" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<Paragraph TextAlignment="center" FontSize="22pt" FontFamily="arial">Test Paragraph</Paragraph>
<Paragraph TextAlignment="center" FontFamily="arial">Test second paragraph</Paragraph>
</FlowDocument>
If I resize the fonts the content is only resized vertically (please note that the stretch direction is set to both). Any ideas?
I had a similar problem with FlowDocumentScrollView, but this solution also seems to work with FlowDocumentPageView:
The FlowDocument is centered because it's PagePadding property is set to auto,auto,auto,auto. Setting PagePadding to 0 fixes this behavior.
<FlowDocumentScrollViewer VerticalScrollBarVisibility="Auto">
<FlowDocument PagePadding="0">
</FlowDocument>
</FlowDocumentScrollViewer>
The following lines are causing your elements to center themselves (which is not the same as stretch):
viewer.VerticalAlignment = VerticalAlignment.Center;
viewer.HorizontalAlignment = HorizontalAlignment.Center;
pageView.VerticalAlignment = VerticalAlignment.Center;
pageView.HorizontalAlignment = HorizontalAlignment.Center;
You can safely remove them, as the default alignment here is Stretch.
If you still want to center the viewer, explicitly define the page size (remember, there are 96 points in an inch, and the Margin and PageSize are set in points):
Width= 96 * 8.5
Height= 96 * 11
Could you specify where and how do you use the result of your GetPage() method? Is it xbap or desktop application?
I'm asking this, because the following document is displayed just perfectly right in Kaxaml:
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<FlowDocumentPageViewer>
<FlowDocument >
<Paragraph TextAlignment="center" FontSize="22pt" FontFamily="arial">Test Paragraph</Paragraph>
<Paragraph TextAlignment="center" FontFamily="arial">Test second paragraph</Paragraph>
</FlowDocument>
</FlowDocumentPageViewer>
</Grid>
</Page>
PS: If it's a desktop application you can always find who causes problems by Snoop tool, form Pete Blois.
Update: Its a desktop application, the getpage() result is posted into a grid which docks/fills perfectly.
<Window x:Class="GreenWebPlayerWPF.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="Auto" Width="Auto" WindowStyle="None" WindowState="Maximized" WindowStartupLocation="CenterScreen" Loaded="Window_Loaded" Closing="Window_Closing">
<Grid Width="Auto" Height="Auto" Name="TransitionContainer" Background="White" Margin="0">
//here the result from GetPage() method is inserted
</Grid>
</Window>
(this comment is written from another account)
#Anvaka: What i mean by perfectly right is that the document should "dock in container" that is the fonts should resize, it should fill the container in height and width. Now that im thinking about it, that may not seem like a proper behaviour for a flowdocument.
When i put the flow document in the container it is centered in middle of parent container (so far so good). but the parent container is not filling out its parent container so when i zoom or change font size, i would like the documentPageView container to grow in width and height, but remain centered.
Is it possible to change or modify a specific part of a control template without having to recreate the entire control template of the control in the xaml?
For example, I was trying to get rid of the border of a textbox, so I could throw together a basic search box with rounded corners (example xaml below). Setting the borderthickness to 0 works fine, until you mouse over the textbox and a pseudo border they added to the control flashes up. If I look at the controltemplate for the textbox, I can even see the visual state is named, but cannot think of how to disable it.
Without overriding the control template of the TextBox, how would I stop the Visual State Manager firing the mouse over effect on the TextBox?
<Border Background="White" CornerRadius="10" VerticalAlignment="Center" HorizontalAlignment="Center" BorderThickness="3" BorderBrush="#88000000">
<Grid VerticalAlignment="Center" HorizontalAlignment="Center" Width="200" Margin="5,0,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="16" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Path Height="13" Width="14" Stretch="Fill" Stroke="#FF000000" StrokeThickness="2" Data="M9.5,5 C9.5,7.4852815 7.4852815,9.5 5,9.5 C2.5147185,9.5 0.5,7.4852815 0.5,5 C0.5,2.5147185 2.5147185,0.5 5,0.5 C7.4852815,0.5 9.5,2.5147185 9.5,5 z M8.5,8.4999971 L13.5,12.499997" />
<TextBox GotFocus="TextBox_GotFocus" Background="Transparent" Grid.Column="1" BorderThickness="0" Text="I am searchtext" Margin="5,0,5,0" HorizontalAlignment="Stretch" />
</Grid>
</Border>
I've found a way to do this, by inheriting off the control and overriding the OnApplyTemplate. It's not ideal, but I think it's better than having to copy the entire control template. Here's an example of creating a borderless textbox, essentially disabling the mouse over visual state by always clearing the storyboard:
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Animation;
namespace SilverlightTestApplication
{
public class BorderlessTextBox : TextBox
{
public BorderlessTextBox()
{
BorderThickness = new System.Windows.Thickness(0);
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
//Get the mouse over animation in the control template
var MouseOverVisualState = GetTemplateChild("MouseOver") as VisualState;
if (MouseOverVisualState == null)
return;
//get rid of the storyboard it uses, so the mouse over does nothing
MouseOverVisualState.Storyboard = null;
}
}
}
Its been awhile since I used XAML, but no, I don't believe you can just modify a piece of the template.
However if you have the IDE you can create a copy of the currently applied template and just modify the piece you want and leave the rest as is. See the How to Edit section of this link.
Retrieve the default template of every control, with the XAML reader, then copy/paste and modify what you want... not very clean but I think this is the only way (I'm searching how to retrieve this default template)
In WPF, not sure about silverlight here a snippet of code to retrieve the template of Aero, you can try to copy/paste and change what you want:
public Window1()
{
InitializeComponent();
using(FileStream fs = new FileStream("C:/TextBoxTemplate.xaml", FileMode.Create))
{
var res = LoadThemeDictionary(typeof(TextBox), "Aero", "NormalColor");
var buttonRes = res[typeof(TextBox)];
XamlWriter.Save(buttonRes, fs);
}
}
public static ResourceDictionary LoadThemeDictionary(Type t,
string themeName, string colorScheme)
{
Assembly controlAssembly = t.Assembly;
AssemblyName themeAssemblyName = controlAssembly.GetName();
object[] attrs = controlAssembly.GetCustomAttributes(
typeof(ThemeInfoAttribute), false);
if(attrs.Length > 0)
{
ThemeInfoAttribute ti = (ThemeInfoAttribute)attrs[0];
if(ti.ThemeDictionaryLocation ==
ResourceDictionaryLocation.None)
{
// There are no theme-specific resources.
return null;
}
if(ti.ThemeDictionaryLocation ==
ResourceDictionaryLocation.ExternalAssembly)
{
themeAssemblyName.Name += "." + themeName;
}
}
string relativePackUriForResources = "/" +
themeAssemblyName.FullName +
";component/themes/" +
themeName + "." +
colorScheme + ".xaml";
Uri resourceLocater = new System.Uri(
relativePackUriForResources, System.UriKind.Relative);
return Application.LoadComponent(resourceLocater)
as ResourceDictionary;
}
I 've never used Silverlight, but I don't think there is a lot of things to do to adapt this template to Silverlight.
Source : Default template in WPF