WPF: Placeholder - wpf

It's the following situation:
I've a WPF project with three textboxes. In these textboxes is the content something like this:
Textbox 1:
net.tcp://server1:61594/printerengine/printerserver
Textbox 2:
net.tcp://server1:61594/printerengine/printeradmin
Textbox 3:
net.tcp://server1:61594/printerengine/printeradmin
Because of the reason the paths stay the same all the time and only the server name changes, there should be an extra textbox for the server name only.
In the textbox 4 should be the server name filled in only:
Textbox 4:
server1
If you want to change the server name, it should be possible to change it in the textbox 4 and it should automatically rename the server name in the path in textbox 1-3.
I'm hoping you can understand me and give me a little bit help.
Greetings,
Lars
thank you for your answer. Not really sure if it would help me but I found this tutorial:
http://msdn.microsoft.com/de-de/library/system.windows.data.ivalueconverter.aspx
This is written in C# but I rewrote it to WPF:
This is my code:
Public Class DateConverter
Implements IValueConverter
Public Function Convert(value As Object, targetType As Type, parameter As Object) As Object
Dim [date] As DateTime = DirectCast(value, DateTime)
Return [date].ToShortDateString()
End Function
Public Function ConvertBack(value As Object, targetType As Type, parameter As Object) As Object
Dim strValue As String = value.ToString()
Dim resultDateTime As DateTime
If DateTime.TryParse(strValue, resultDateTime) Then
Return resultDateTime
End If
Return value
End Function
Public Function Convert1(value As Object, targetType As System.Type, parameter As Object, culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.Convert
End Function
Public Function ConvertBack1(value As Object, targetType As System.Type, parameter As Object, culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.ConvertBack
End Function
End Class
And this is my XAML:
<Window x:Class="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">
<Grid>
<src:DateConverter x:Key="dateConverter"/>
<TextBlock Grid.Row="2" Grid.Column="0" Margin="0,0,8,0"
Name="startDateTitle"
Style="{StaticResource smallTitleStyle}">Start Date:</TextBlock>
<TextBlock Name="StartDateDTKey" Grid.Row="2" Grid.Column="1"
Text="{Binding Path=StartDate, Converter={StaticResource dateConverter}}"
Style="{StaticResource textStyleTextBlock}"/>
</Grid>
</Window>
Not really working. Anyone who can help me? Thank you.
Greetings,
Lars

Try to use StringFormat, something like this -
<TextBlock Text="{Binding Path=Text, ElementName=Textbox4Name,
StringFormat='net.tcp://\{0\}/printerengine/printerserver' />
refer - http://elegantcode.com/2009/04/07/wpf-stringformat-in-xaml-with-the-stringformat-attribute/

Related

Wpf UserControl with its own data context and external dependency property

I'm trying to create a simple AudioPlayer control multiple reuse in a solution I'm working on. I have seen numerous example in various posts and blogs around the net and from those have created a small control with four buttons.
The xaml is defined thus:
<UserControl x:Class="AudioPlayer"
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="30" d:DesignWidth="150">
<StackPanel Orientation="Horizontal">
<StackPanel.Resources>
<Style TargetType="{x:Type Button}">
<Setter Property="Margin" Value="10,0,0,0" />
</Style>
</StackPanel.Resources>
<MediaElement Name="media" Source="{Binding Source}" LoadedBehavior="{Binding LoadedBehavior}"/>
<Button Width="24" Height="24" x:Name="Repeat" Background="Transparent" BorderBrush="Transparent">
<Image Source="Images/button_blue_repeat.png" ToolTip="Repeat"/>
</Button>
<Button Width="24" Height="24" x:Name="Play" Background="Transparent" BorderBrush="Transparent">
<Image Source="Images/button_blue_play.png" ToolTip="Play"/>
</Button>
<Button Width="24" Height="24" x:Name="Pause" Background="Transparent" BorderBrush="Transparent">
<Image Source="Images/button_blue_pause.png" ToolTip="Pause"/>
</Button>
<Button Width="24" Height="24" x:Name="Stop" Background="Transparent" BorderBrush="Transparent">
<Image Source="Images/button_blue_stop.png" ToolTip="Stop"/>
</Button>
</StackPanel>
With fairly simple code in the background;
Public Class AudioPlayer
Public Sub New()
InitializeComponent()
DataContext = New AudioPlayerViewModel With {.MediaElement = media, .Source = "bag1.mp3", .LoadedBehavior = MediaState.Manual, .CanCommandExecute = True}
End Sub
End Class
Public Class AudioPlayerViewModel
Inherits DependencyObject
Public Sub New()
Me.MediaCommand = New MediaElementCommand(Me)
End Sub
Public Property MediaElement() As MediaElement
Public Property Source() As String
Public Property LoadedBehavior() As MediaState
Public Property CanCommandExecute() As Boolean
Public Property MediaCommand() As ICommand
End Class
Public Class MediaElementCommand
Implements ICommand
Private vm As AudioPlayerViewModel
Public Sub New(ByVal vm As AudioPlayerViewModel)
Me.vm = vm
End Sub
Public Function CanExecute(ByVal parameter As Object) As Boolean Implements ICommand.CanExecute
Return vm.CanCommandExecute
End Function
Public Custom Event CanExecuteChanged As EventHandler Implements ICommand.CanExecuteChanged
AddHandler(ByVal value As EventHandler)
AddHandler CommandManager.RequerySuggested, value
End AddHandler
RemoveHandler(ByVal value As EventHandler)
RemoveHandler CommandManager.RequerySuggested, value
End RemoveHandler
RaiseEvent(ByVal sender As System.Object, ByVal e As System.EventArgs)
End RaiseEvent
End Event
Public Sub Execute(ByVal parameter As Object) Implements ICommand.Execute
Dim action As String = DirectCast(parameter, String)
Select Case action.ToLower()
Case "play"
vm.MediaElement.Position = TimeSpan.Zero
vm.MediaElement.Play()
Case "stop"
vm.MediaElement.Stop()
Case "pause"
vm.MediaElement.Pause()
Case "resume"
vm.MediaElement.Play()
Case Else
Throw New NotSupportedException(String.Format("Unknown media action {0}", action))
End Select
End Sub
End Class
My question quite simply is this. From the code you can see that at present the sound that is being played is hard coded. What I would like to know is wheteher it would be possible to create a dependency property for this control (I presume it would be of type string to represent a path to a sound file but I'm not sure) so that when the control is created in other controls or windows their viewmodels can pass a sound property to it (if that makes sense!).
If it is possible where should I create it in respect of the code snippets shown?
Many thanks
You could create a DP, but it would not work the way users would expect.
For example, if the user were to write
<local:AudioPlayer Media="{Binding SomeString}" />
Then WPF tries to set Media = DataContext.SomeString
But since you have hardcoded DataContext = New AudioPlayerViewModel in the constructor, then the binding will most likely fail because users will be expecting their inherited DataContext to be used by the UserControl, but the hardcoded DataContext will be used instead.
It is always my advice to never hardcode the DataContext property inside of a UserControl. It breaks the entire WPF design pattern of having separate layers for UI and Data.
Either build a UserControl specifically for use with a specific Model or ViewModel being used as the DataContext, such as this :
<!-- Draw anything of type AudioPlayerViewModel with control AudioPlayer -->
<!-- DataContext will automatically set to the AudioPlayerViewModel -->
<DataTemplate DataType="{x:Type local:AudioPlayerViewModel}}">
<local:AudioPlayer />
</DataTemplate>
Or build it with the expectation that the DataContext can be absolutely anything, and DependencyProperites will be used to give the control the data it needs :
<!-- DataContext property can be anything, as long as it as the property MyString -->
<local:AudioPlayer Media="{Binding MyString}" />
The easiest way to get your code to work would probably be
Create the ViewModel as a private property instead of assiging it to the UserControl.DataContext
Bind or set the DataContext of the top level child inside your UserControl to your private property (in your case, the StackPanel)
Adjust the binding for your MediaElement to read from a custom DependencyProperty instead of from StackPanel.DataContext
Something like this :
<UserControl x:Name="MyAudioPlayer" ...>
<StackPanel x:Name="AudioPlayerRoot">
...
<MediaElement Source="{Binding ElementName=MyAudioPlayer, Path=MediaDependecyProperty}" ... />
...
</StackPanel>
</UserControl>
Public Sub New()
InitializeComponent()
AudioPlayerRoot.DataContext = New AudioPlayerViewModel ...
End Sub

Display text with a string in Textblock xaml

I have a textblock, and I want to display a text with a defined string. How to do it?
The textblock:
<TextBlock HorizontalAlignment="Left" TextWrapping="Wrap" Padding="6" VerticalAlignment="Center" Margin="45,0,0,0" Height="30" Width="386" Text="My Program ver. Version"/>
My string:
Public Version As String = "1.0a"
You can use StringFormat.
<TextBlock Text="{Binding Path=Version, StringFormat=My Program ver. {0}}" />
In your code- behind you must change Version to property (this property should be ReadOnly because it isn't change in runtime) and assign DataContext in constructor:
Class MainWindow
Public Sub New()
InitializeComponent()
Me.DataContext = Me
End Sub
ReadOnly Property Version As String
Get
Return "1.0a"
End Get
End Property
End Class
If you want your TextBlock to update the version number every time you have a new version,
you can do it like this in C#. You can probably find out easily how to write this in VB.
This will update your TextBlock everytime you publish a new version of your program.
In XAML you bind a TextBlock text to "Version":
<TextBlock Text="{Binding Version, Mode=OneWay}" />`
And then in code-behind or in your view-model you can use a property for that Binding that you have in the XAML TextBlock:
public string Version
{
get
{
return String.Format("VERSION: {0}",DeploymentInfo.Version.ToString());
}
}
Then you need to add a reference to "System.Deployment" in your project.
This will only work when you have done a "PUBLISH" of your project. When you start the debugger you will probably only see version number: 0.0.0.0
In XAML file:
First you should name your TextBlock i have gave tbWithNoName for example.
<TextBlock x:Name="tbWithNoName" HorizontalAlignment="Left" TextWrapping="Wrap" Padding="6" VerticalAlignment="Center" Margin="45,0,0,0" Height="30" Width="386" Text="My Program ver. Version"/>
Then add Loaded call on Window object.
<Window x:Class="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"
Loaded="Window_Loaded">
Insert Window_Loaded function to your vb file.
Private Sub Window_Loaded(sender As Object, e As RoutedEventArgs)
tbWithNoName.Text = tbWithNoName.Text + " " + Version
End Sub
This will change TextBlock's Text when Window loaded

Setting content of TextBlock and text of HyperlinkButton in silverlight custom control

I am trying to create a custom control that will display a hyperlink button with some text below the link. The idea is to have urgent messages show up on a screen of a Silverlight page. From what I have read, I thought that I should be able to create a new control and then create some dependancy properties and bind the dynamic parts of the component pieces to them in order to allow me to add multiple instances of the custom control to my Silverlight project. Here is my XAML that defines the control
<UserControl
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"
x:Class="WhatsNew.UrgentStoryGridControl"
d:DesignWidth="608" d:DesignHeight="65" Background="White">
<UserControl.Resources>
<Style x:Key="WhatsNewTitleStyle" TargetType="HyperlinkButton">
Removed for Brevity
</Style>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Height="65" Margin="0" VerticalAlignment="Bottom" Background="White">
<StackPanel>
<HyperlinkButton Style="{StaticResource WhatsNewTitleStyle}" Content="{Binding linkText}" HorizontalAlignment="Left" VerticalAlignment="Top" NavigateUri="{Binding linkURI}" Foreground="Red"/>
<TextBlock Style="{StaticResource WhatsNewTextStyle}" Text="{Binding storyText}" Margin="0,13,0,0" d:LayoutOverrides="Height"/>
</StackPanel>
</Grid>
In the code behind, I have created three dependancy properties
Partial Public Class UrgentStoryGridControl
Inherits UserControl
Public Shared linkTextProperty As DependencyProperty = DependencyProperty.Register("linkText", GetType(String), GetType(UrgentStoryGridControl), New PropertyMetadata("Link Text"))
Public Shared linkURIProperty As DependencyProperty = DependencyProperty.Register("linkURI", GetType(String), GetType(UrgentStoryGridControl), New PropertyMetadata("link.html"))
Public Shared storyTextProperty As DependencyProperty = DependencyProperty.Register("storyText", GetType(String), GetType(UrgentStoryGridControl), New PropertyMetadata("Story Text"))
Public Property linkText() As String
Get
Return GetValue(linkTextProperty)
End Get
Set(ByVal value As String)
SetValue(linkTextProperty, value)
End Set
End Property
Public Property linkURI() As String
Get
Return GetValue(linkURIProperty)
End Get
Set(ByVal value As String)
SetValue(linkURIProperty, value)
End Set
End Property
Public Property storyText As String
Get
Return GetValue(storyTextProperty)
End Get
Set(ByVal value As String)
SetValue(storyTextProperty, value)
End Set
End Property
End Class
When I place this control on my Silverlight project using Expression Blend, I see the three properties listed in the Miscellaneous section of the properties window as I would expect. The values from the PropertyMetadata are populated as the default values for these properties. Here is the code from my Silverlight project where I leave the default values alone:
<local:UrgentStoryGridControl x:Name="urgentStory" Height="65" />
Here is the code where I try to set the values to something:
<local:UrgentStoryGridControl x:Name="urgentStory" Height="65" linkText="Test Link Text" linkURI="testpage.html" storyText="Sample Story Text" />
Either way I attempt to use the control, I'm not getting anything displayed when I launch the application. I figure that I'm missing something small but after having spent a lot of time today researching this, I'm not finding anything that would indicate what I'm missing or doing wrong.
You need to set the DataContext in your custom UserControl or else your bindings won't work.
In your UrgentStoryGridControl's constructor, you should be able to set Me.DataContext = Me

WPF DataGrid and Avalon TimePicker binding is not working

I'm using a the WPF DataGrid from the wpf toolkit and a TimePicker from AvalonControlsLibrary to insert a collection of TimeSpans. My problem is that bindings are not working inside the DataGrid, and I have no clue of why this isn't working.
Here is my setup:
I have the following XAML:
<Window x:Class="TestMainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:wpf="http://schemas.microsoft.com/wpf/2008/toolkit" xmlns:a="http://schemas.AvalonControls/AvalonControlsLibrary/Controls" SizeToContent="WidthAndHeight" MinHeight="250" MinWidth="300">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<GroupBox Grid.Row="0">
<GroupBox.Header>
Testing it:
</GroupBox.Header>
<wpf:DataGrid ItemsSource="{Binding Path=TestSpans}" AutoGenerateColumns="False">
<wpf:DataGrid.Columns>
<wpf:DataGridTemplateColumn Header="Start">
<wpf:DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<a:TimePicker SelectedTime="{Binding Path=Span, Mode=TwoWay}" />
</DataTemplate>
</wpf:DataGridTemplateColumn.CellEditingTemplate>
<wpf:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Span}" />
</DataTemplate>
</wpf:DataGridTemplateColumn.CellTemplate>
</wpf:DataGridTemplateColumn>
</wpf:DataGrid.Columns>
</wpf:DataGrid>
</GroupBox>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Grid.Row="1">
<a:TimePicker SelectedTime="{Binding Path=SelectedTime, Mode=TwoWay}" />
</StackPanel>
</Grid>
And this is my ViewModel:
Imports System.Collections.ObjectModel
Public Class TestMainWindowViewModel
Private _selectedTime As TimeSpan = DateTime.Now.TimeOfDay
Public Property SelectedTime() As TimeSpan
Get
Return _selectedTime
End Get
Set(ByVal value As TimeSpan)
_selectedTime = value
End Set
End Property
Private _testSpans As ObservableCollection(Of TimeSpanContainer) = New ObservableCollection(Of TimeSpanContainer)
Public Property TestSpans() As ObservableCollection(Of TimeSpanContainer)
Get
Return _testSpans
End Get
Set(ByVal value As ObservableCollection(Of TimeSpanContainer))
_testSpans = value
End Set
End Property
Public Sub New()
_testSpans.Add(DateTime.Now.TimeOfDay)
_testSpans.Add(DateTime.Now.TimeOfDay)
_testSpans.Add(DateTime.Now.TimeOfDay)
End Sub
End Class
Public Class TimeSpanContainer
Private _span As TimeSpan
Public Property Span() As TimeSpan
Get
Return _span
End Get
Set(ByVal value As TimeSpan)
_span = value
End Set
End Property
Public Sub New(ByVal t As TimeSpan)
_span = t
End Sub
End Class
I'm starting this window in application.xaml.vb like this:
Class Application
' Application-level events, such as Startup, Exit, and DispatcherUnhandledException
' can be handled in this file.
Protected Overrides Sub OnStartup(ByVal e As System.Windows.StartupEventArgs)
MyBase.OnStartup(e)
Dim window As TestMainWindow = New TestMainWindow
window.DataContext = New TestMainWindowViewModel()
window.Show()
End Sub
End Class
EDIT 1: I forgot to mention that the binding to SelectedTime TimeSpan works as expected. The problem are the bindings inside the DataGrid.
EDIT 2: Changed example a little bit to show the problem better.
What do you mean by your bindings aren't working? Are you getting no value in the timepicker control when you attempt to edit the value?
Edit:
Ok, I was having this same issue yesterday and I think there is 2 parts to the issue.
If there is no value appearing in the TimePicker control when you switch to edit mode then there is probably a binding issue with the control.
The binding to the underlying value I found to be an issue with using the DataGridTemplateColumn. Basically the grid doesnt handle your databinding back using the same mechanisms of regular bound columns. What it means is you need to perform the following binding on your controls within the column:
SelectedTime="{Binding Span, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
This will fix the binding back to the underlying object. However if there is still an issue with the control it may not help you much. Sorry but I haven't used AvalonControlsLibrary so not sure if there is a potential problem there. Fixing step 2 solved my issues.
Cheers
-Leigh
I know this is an old question, but I where playing with this exact control having the exact same issue. I looked in the TimePicker class of AvalonControlsLibrary and the constructor looks like this
/// <summary>
/// Default constructor
/// </summary>
public TimePicker()
{
SelectedTime = DateTime.Now.TimeOfDay;
}
Removing the line setting the SelectedTime restored the databinding behaviour for me making your posted example work as intended.

WPF Hide DataGridColumn via a binding

For some reason I can't hide WPF Toolkit's DataGridColumn. I am trying to do the following:
<dg:DataGridTemplateColumn Header="Item Description" Visibility="{Binding IsReadOnly}">
<dg:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding Path=ItemDescription}" />
</DataTemplate>
</dg:DataGridTemplateColumn.CellTemplate>
This doesn't work, since it's looking for a IsReadOnly property on the ItemSource (not a property of the current class).
If add this as a property of the ItemSource class that implements INoifyPropertyChanged, it still doesn't hide the column. Is there a way around this? I want the column to hid when a button click changes IsReadOnly property.
Assume IsReadOnly returns a Visibility value and is a dependency property
I am completely stuck, I would really appreciate the help! Thanks a lot!
Posted in this question:
WPF DataGrid: Binding DataGridColumn visibility to ContextMenu MenuItems Ischeked (MVVM)
Fubzot is using the binding code similar to
Visibility='{Binding (FrameworkElement.DataContext).IsReadOnly,
RelativeSource={x:Static RelativeSource.Self}}'
You may also want to check out this:
Forwarding the DataGrid’s DataContext to its’ columns..
which is also linked in the above question.
Just for my information: Do you see any Binding errors in your Output window using your current code?
If you want to bind to the DataGridColumn's IsReadOnly property, just add a RelativeSource to the Binding (and a converter):
<BooleanToVisibilityConverter x:Key="boolToVis" />
...
<dg:DataGridTemplateColumn Header="Item Description" Visibility="{Binding IsReadOnly, RelativeSource={RelativeSource Self}, Converter={StaticResource boolToVis}}">
Also, it looks like this StackOverflow question might be related to your problem.
you need to use a converter
Public Class BooleanToVisibilityConverter
Implements IValueConverter
Public Function Convert(ByVal value As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements IValueConverter.Convert
If targetType Is GetType(Visibility) Then
If CBool(value) = True Then
Return Visibility.Hidden
Else
Return Visibility.Visible
End If
Else
Return Nothing
End If
End Function
Public Function ConvertBack(ByVal value As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements IValueConverter.ConvertBack
Return Nothing
End Function
End Class
then you use the converter in the XAML. SAMPLE

Resources