Change user control appearance based on state - wpf

I have a user control that consists of four overlapping items: 2 rectangles, an ellipse and a lable
<UserControl x:Class="UserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="50.1" Height="45.424" Background="Transparent" FontSize="24">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="3.303*" />
<RowDefinition Height="40*" />
<RowDefinition Height="2.121*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="5.344*" />
<ColumnDefinition Width="40.075*" />
<ColumnDefinition Width="4.663*" />
</Grid.ColumnDefinitions>
<Rectangle Name="Rectangle1" RadiusX="5" RadiusY="5" Fill="DarkGray" Grid.ColumnSpan="3" Grid.RowSpan="3" />
<Ellipse Name="ellipse1" Fill="{Binding State}" Margin="0.016,0.001,4.663,0" Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" Stroke="Black" IsEnabled="True" Panel.ZIndex="2" />
<Label Name="lblNumber" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Foreground="White" FontWeight="Bold" FontSize="24" Grid.Column="1" Grid.Row="1" Padding="0" Panel.ZIndex="3">9</Label>
<Rectangle Grid.Column="1" Grid.Row="1" Margin="0.091,0,4.663,0" Fill="Blue" Name="rectangle2" Stroke="Black" Grid.ColumnSpan="2" Panel.ZIndex="1" />
</Grid>
Here is my business object that I want to control the state of my user control:
Imports System.Data
Imports System.ComponentModel
Public Class BusinessObject
Implements INotifyPropertyChanged
Public logger As log4net.ILog
Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
Private _state As States
Public Enum States
State1
State2
State3
End Enum
Public Property State() As States
Get
Return _state
End Get
Set(ByVal value As States)
If (value <> _state) Then
_state = value
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("State"))
End If
End Set
End Property
Protected Sub OnPropertyChanged(ByVal name As String)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(name))
End Sub
I want to be able to change the state of a business object in the code behind and have that change the colors of multiple shapes in my usercontrol. I'm not sure about how to do the binding. I set the datacontext of the user control in the code behind but not sure if that's right. I'm new to WPF and programming in general and I'm stuck on where to go from here. Any recommendations would be greatly appreciated!!

A simple way would be to use a value converter. Basically this is a class that allows you to bind on a value in your BusinessObject, and depending on what the value is, you return a different brush.
Here is an example showing you exactly how to do it.
[ValueConversion(typeof(States), typeof(Brush))]
public class ColorConverter : IValueConverter
{
public object Convert(object value, Type targetType,
object parameter, CultureInfo culture)
{
/* return a different brush depending on the state */
}
}
Then you bind it like this:
<Ellipse Fill="{Binding State, Converter={StaticResource colorConverter} />
Look at the link I provided above to see the full example.
The advantage of this way over Rachel's answer is that it is a generic implementation, so you don't have to create a template for each of your shapes if you want to have this apply to different objects (rectangle, ellipse, etc...). But Rachel's answer - i.e. using a template, is nice too, because it doesn't require any code.

You would create a trigger based on State property, and if it is equal to StateX you would change the color. For example:
<Rectangle>
<Rectangle.Style>
<Style TargetType="{x:Type Rectangle}">
<Style.Triggers>
<DataTrigger Binding="{Binding State} "
Value="{x:Static localNamespace:States.State1}">
<Setter Property="Fill" Value="Red" />
</DataTrigger>
</Style.Triggers>
</Style>
</Rectangle.Style>
</Rectangle>
The localNamespace you'd have to define yourself in the <UserControl> tag. Something like <UserControl xmlns:localNamespace="clr-namespace:MyNamespace.MyClassWithStateEnum;assembly=MyNamespace"

Related

Bind Element to different DataContext property

forgive this question - just learning WPF and it's making my brain hurt. Can't get my head around Bindings/DataContexts. XAML below produced via some code monkery (my knowledge of WPF not good enough atm to know what is helpful to post or not):
<Window x:Class="MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:s="clr-namespace:MoveResize" WindowStartupLocation="CenterScreen"
xmlns:paz="clr-namespace:Wpf.Controls.PanAndZoom;assembly=Wpf.Controls.PanAndZoom"
Title="Move and resize" Height="550" Width="750" Loaded="Window_Loaded" KeyDown="Window_KeyDown" KeyUp="Window_KeyUp">
<Window.Resources>
<!-- Custom Thumb Style-->
<Style x:Key="SliderThumbStyle" TargetType="{x:Type Thumb}">
<Setter Property="SnapsToDevicePixels" Value="true" />
<Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Thumb}">
<Rectangle x:Name="Rectangle" StrokeThickness="1" Stretch="Fill" Opacity="1">
<Rectangle.Stroke>
<SolidColorBrush Color="Black"></SolidColorBrush>
</Rectangle.Stroke>
<Rectangle.Fill>
<SolidColorBrush Color="Yellow"></SolidColorBrush>
</Rectangle.Fill>
</Rectangle>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- MoveThumb Template -->
<ControlTemplate x:Key="MoveThumbTemplate" TargetType="{x:Type s:MoveThumb}">
<Rectangle Fill="Transparent" />
</ControlTemplate>
<!-- ResizeDecorator Template -->
<ControlTemplate x:Key="ResizeDecoratorTemplate" TargetType="{x:Type Control}">
<Grid>
<!-- Abridged for stackoverflow posting -->
<s:ResizeThumb Style="{StaticResource SliderThumbStyle }" Width="9" Height="9" Cursor="SizeNWSE" VerticalAlignment="Bottom" HorizontalAlignment="Right" />
</Grid>
</ControlTemplate>
<!-- Designer Item Template-->
<ControlTemplate x:Key="DesignerItemTemplate" TargetType="ContentControl">
<Grid DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}">
<s:MoveThumb Template="{StaticResource MoveThumbTemplate}" Cursor="SizeAll" />
<ContentPresenter Content="{TemplateBinding ContentControl.Content}" />
<Control Template="{StaticResource ResizeDecoratorTemplate}" />
</Grid>
</ControlTemplate>
</Window.Resources>
<paz:ZoomBorder x:FieldModifier="public" Name="zoomBorder" Stretch="None" ZoomSpeed="1.2" Background="SlateBlue" ClipToBounds="True" Focusable="True" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Grid.Row="4" Grid.Column="1">
<Canvas x:Name="workspace" Background="#555" Width="1920" Height="1080" Margin="97,93,-1275,-654">
<Path x:Name="YellowDiamond" Fill="Yellow" Data="M 0,5 5,0 10,5 5,10 Z" Stretch="Fill" IsHitTestVisible="True" Canvas.Left="10" Canvas.Top="10" Height="124.75" Width="134.5" />
<ContentControl Width="130" MinWidth="50" Height="130" MinHeight="50" Canvas.Top="150" Canvas.Left="150" Template="{StaticResource DesignerItemTemplate}">
<Path x:Name="BlueDiamond" Fill="Blue" Data="M 0,5 5,0 10,5 5,10 Z" Stretch="Fill" IsHitTestVisible="False" />
</ContentControl>
<TextBox x:Name="widthTB" Height="23" Canvas.Left="131" TextWrapping="Wrap" Text="{Binding BastardWidth, Mode=OneWay}" Canvas.Top="348" Width="120" />
</Canvas>
</paz:ZoomBorder>
</Window>
The key line is:
<s:ResizeThumb Style="{StaticResource SliderThumbStyle }" Width="9" Height="9" Cursor="SizeNWSE" VerticalAlignment="Bottom" HorizontalAlignment="Right" />
I'm wanting to set Width and Height to a property stored in certain class (PanAndZoomController). My understanding is that this is presently databound to ResizeThumb.vb. The relevant code behind:
Partial Public Class MainWindow
Private _panZoomControl As New PanAndZoomController
Public Property PanZoomController() As PanAndZoomController
Get
Return _panZoomControl
End Get
Set(ByVal value As PanAndZoomController)
_panZoomControl = value
End Set
End Property
Public Sub New()
InitializeComponent()
End Sub
Private Sub Window_Loaded(sender As Object, e As RoutedEventArgs)
Me.DataContext = _panZoomControl
End Sub
Private Sub MousewheelMoved(sender As Object, e As MouseWheelEventArgs) Handles Me.MouseWheel
_panZoomControl.ZoomFactor = zoomBorder.ZoomX
End Sub
End Class
Public Class PanAndZoomController
Private _zoomFactor As Double
Public Property ZoomFactor() As Double
Get
Return _zoomFactor
End Get
Set(ByVal value As Double)
_zoomFactor = value
_scaledWidth = 10 * _zoomFactor
End Set
End Property
Private _scaledWidth As Double = 10
Public Property ScaledWidth() As Double
Get
Return _scaledWidth
End Get
Set(ByVal value As Double)
_scaledWidth = value
End Set
End Property
End Class
Thus, Width and Height should be populated from MainWindow.PanZoomController.ScaledWidth. Could someone help out with how to achieve this? In as little XAML as possible, please!? I still need to preserve the binding of that element to s:ResizeThumb due to the code behind.
EDIT: In response to ASh's suggestions.
I've tried NotifyPropertyChanged with what I think is the right way, but still no joy :(
Simplified code scenario. Relevant code behind:
Public Class Workspace
Implements INotifyPropertyChanged
Public Sub NotifyPropertyChanged(ByVal propName As String)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propName))
End Sub
Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
Private _canvasZoomFactor As Double = 1
Public Property CanvasZoomFactor() As Double
Get
Return _canvasZoomFactor
End Get
Set(ByVal value As Double)
_canvasZoomFactor = value
_handleWidth = 5 * value
Me.NotifyPropertyChanged("HandleWidth")
End Set
End Property
Private _handleWidth As Double = 5
Public ReadOnly Property HandleWidth() As Double
Get
Return _handleWidth
End Get
End Property
End Class
XAML:
<UserControl x:Name="MainWorkspace" x:Class="Workspace"
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"
xmlns:s="clr-namespace:stigzler.utility.WPFcontrols"
xmlns:local="clr-namespace:stigzler.utility.WPFcontrols"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<ControlTemplate x:Key="ResizeDecoratorTemplate" TargetType="{x:Type Control}">
<Grid SnapsToDevicePixels="false">
<s:ResizeThumb Width="{Binding ElementName=Workspace, Path=HandleWidth,UpdateSourceTrigger=PropertyChanged}"
Height="{Binding ElementName=Workspace, Path=HandleWidth,UpdateSourceTrigger=PropertyChanged}"
Style="{StaticResource SliderThumbStyle}" Cursor="SizeNWSE" VerticalAlignment="Top"
HorizontalAlignment="Left" />
</Grid>
</ControlTemplate>
<ControlTemplate x:Key="DesignerItemTemplate" TargetType="ContentControl">
<Grid DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}">
<ContentPresenter Content="{TemplateBinding ContentControl.Content}" />
<Control Template="{StaticResource ResizeDecoratorTemplate}" />
</Grid>
</ControlTemplate>
<ContentControl Width="130" MinWidth="50" Height="130" MinHeight="50" Canvas.Top="150" Canvas.Left="150" Template="{StaticResource DesignerItemTemplate}">
<Path x:Name="BlueDiamond" Fill="Blue" Data="M 0,5 5,0 10,5 5,10 Z" Stretch="Fill" IsHitTestVisible="False" />
</ContentControl>
</UserControl>
Relevant lines:
<s:ResizeThumb Width="{Binding ElementName=Workspace, Path=HandleWidth,UpdateSourceTrigger=PropertyChanged}"
Me.NotifyPropertyChanged("HandleWidth")
Still getting no joy. Any other suggestions (I'm still really struggling to get my head around this binding lark).
"My understanding is that this is presently databound to ResizeThumb.vb" - there can't be a binding to a file with code.
Each binding must have a source to get values. There are some options to provide that source:
specify it directly, e.g.: "{Binding Source={StaticResource}}";
use DataContext - the default option: "{Binding Path=SomeProperty}" - when no source is provided, then the binding will try to find requested property in a DataContext - some data associated with the View (or with part of the View - one might want to work with different data in different parts). Usually there is one DataContext per view (Me.DataContext = _panZoomControl)
use other element as binding source (via RelativeSource or ElementName), if the element are in the same view.
s:ResizeThumb is inside MainWindow view, so RelativeSource should work:
<s:ResizeThumb Style="{StaticResource SliderThumbStyle}"
Width="{Binding Path=PanZoomController.ScaledWidth, RelativeSource={RelativeSource AncestorType = {x:Type s:MainWindow}}}"
Height="{Binding Path=PanZoomController.ScaledWidth, RelativeSource={RelativeSource AncestorType = {x:Type s:MainWindow}}}"
hint: when binding doesn't work for some reason, check Output window in Visual Studio - there can be a message describing binding problem (type mismatch, missing property, incorrect DataContext are common reasons)
In addition to #ASh's answer (+1) on how to actually bind to the properties, you should also implement the INotifyPropertyChanged interface in your PanAndZoomController class in order for the view to be refreshed whenever you set the ZoomFactor and ScaledWidth properties dynamically:
Public Class PanAndZoomController
Implements INotifyPropertyChanged
Private _zoomFactor As Double
Public Property ZoomFactor() As Double
Get
Return _zoomFactor
End Get
Set(ByVal value As Double)
_zoomFactor = value
NotifyPropertyChanged(NameOf(ZoomFactor))
ScaledWidth = 10 * _zoomFactor
End Set
End Property
Private _scaledWidth As Double = 10
Public Property ScaledWidth() As Double
Get
Return _scaledWidth
End Get
Set(ByVal value As Double)
_scaledWidth = value
NotifyPropertyChanged(NameOf(ScaledWidth))
End Set
End Property
Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
Protected Sub NotifyPropertyChanged(info As String)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(info))
End Sub
End Class

WPF:change background color of listview item

how to change the foreground(even Background will do) of item in listview.
i have a program which opens excel and check for broken links in the given sheet.
i want to display the user the list of given links and whcih ever is broken. i want to change foreground to RED.
i have bound the values to observablecollection. the collection is just collection of strings(WEB LINKS) and is working fine
should i do multi binding like here
EDIT:-
have got one more problem on this. after creating the property and making all the changes. the WPF form is not getting updated with the values. i.e. the list box is not getting filled. neither the coloring is happening( not sure it is happening also. as i cant see them).
here is my code. please excuse my coding i am new to WPF
<Window x:Class="URLValide.MainWindow"
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:Local="clr-namespace:URL_Validater.URLValide"
Title="URL Validator" Height="269" Width="525" FontSize="13"
ResizeMode="NoResize">
<Window.Resources>
<ResourceDictionary>
<Style x:Key="HighLight" TargetType="{x:Type Control}">
<Setter Property="Background" Value="Honeydew"/>
<Setter Property="FontWeight" Value="UltraBlack"/>
<Style.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="Effect">
<Setter.Value>
<DropShadowEffect BlurRadius="40" Color="Beige" Direction="50" Opacity="0.5"/>
</Setter.Value>
</Setter>
<Setter Property="Background" Value="White"/>
</Trigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
</Window.Resources>
<DockPanel LastChildFill="True">
<Label DockPanel.Dock="Top" Name="WinHeader" Height="30" Background="BurlyWood" FontFamily="Calibri" FontSize="20" FontWeight="Bold" FontStretch="Medium" VerticalAlignment="Top" HorizontalAlignment="Stretch" Margin="0,0,0,0" HorizontalContentAlignment="Center" VerticalContentAlignment="Top">URL Validator</Label>
<Grid DockPanel.Dock="Bottom" Background="Beige">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="20" MaxHeight="30"/>
</Grid.RowDefinitions>
<TextBlock Grid.Column="0" Text="Current URL:"></TextBlock>
<TextBlock Grid.Column="1" Text="{Binding strCrnUrl}" Width="370"></TextBlock>
<TextBlock Grid.Column="2" Text="10 of 100" HorizontalAlignment="Left" VerticalAlignment="Center"></TextBlock>
</Grid>
<Grid DockPanel.Dock="Right" Width="154">
<Grid.ColumnDefinitions>
<ColumnDefinition MaxWidth="300" Width="19*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition MaxHeight="55" MinHeight="10" Height="35*" />
<RowDefinition Height="165*" MinHeight="10" />
</Grid.RowDefinitions>
<Label Name="LbleRight" BorderBrush="Black" BorderThickness="1" Margin="0,2" FontSize="13" Content="List Of URL's" Height="30" Grid.ColumnSpan="2" Grid.Row="0"></Label>
<ListView Grid.Row="1" Background="Azure" ItemsSource="{Binding strPdfLst}" IsEnabled="True" Margin="0,0,0,1"></ListView>
</Grid>
<Grid DockPanel.Dock="Left">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="30*" />
<RowDefinition Height="60*" />
</Grid.RowDefinitions>
<Label BorderBrush="Black" Name="lblFleSel" BorderThickness="1" Height="27" Margin="2,2,0,30" HorizontalAlignment="Left" Width="349">Select File To which Contains the list of URL's:</Label>
<TextBox Name="txtbxFleNme" BorderBrush="Black" BorderThickness="1" Margin="2,34,0,0" Style="{StaticResource ResourceKey=HighLight}" HorizontalAlignment="Left" Width="272"></TextBox>
<Button Name="btnFleSlec" Width="69" Height="27" Content="Browse" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="276,32,4,0"></Button>
<Grid Grid.Row="1" Height="118" HorizontalAlignment="Left" Margin="0,1,0,0" Name="OptionGrid" VerticalAlignment="Top" Grid.RowSpan="2">
<StackPanel HorizontalAlignment="Left" VerticalAlignment="Top" Orientation="Horizontal">
<Border BorderBrush="Black" BorderThickness="1" Height="117" Margin="3,1,0,0" HorizontalAlignment="Stretch" Width="350">
<!--<StackPanel HorizontalAlignment="Left" VerticalAlignment="Top" Width="162" Height="118">
</StackPanel>-->
<Grid Height="auto" HorizontalAlignment="Stretch" Width="335">
<Grid.RowDefinitions>
<RowDefinition Height="10*"/>
<RowDefinition Height="10*"/>
<RowDefinition Height="10*"/>
<RowDefinition Height="10*"/>
<RowDefinition Height="10*"/>
</Grid.RowDefinitions>
<CheckBox Name="chkboxHas" VerticalAlignment="Center" HorizontalAlignment="Center">Has Column Headers</CheckBox>
<Label Name="lblDesc" Height="auto" Margin="0,0,204,0" Grid.Row="1" HorizontalContentAlignment="Right" VerticalAlignment="Top">Description Column:</Label>
<ComboBox Grid.Row="1" Name="cmboxDescol" Margin="131,0,0,0" Style="{StaticResource ResourceKey=HighLight}"></ComboBox>
<Label Name="lblUrlCol" Height="auto" Grid.Row="2" Margin="0,0,204,0" HorizontalContentAlignment="Right">URL's Column:</Label>
<ComboBox Name="cmboxUrlCol" Grid.Row="2" Margin="131,0,0,0" Style="{StaticResource ResourceKey=HighLight}"></ComboBox>
<Label Name="lblResCol" Height="auto" Grid.Row="3" Margin="0,0,196,0" HorizontalContentAlignment="Right">Result Column:</Label>
<ComboBox Name="cmboxResCol" Grid.Row="3" Margin="131,0,0,0" Style="{StaticResource ResourceKey=HighLight}"></ComboBox>
<Button Grid.Row="4" HorizontalAlignment="Center" VerticalAlignment="Center" Content="Validate URL links" Name="btnValidate"></Button>
</Grid>
</Border>
</StackPanel>
</Grid>
</Grid>
</DockPanel>
i am not sure if i should be posting full code. but here is my class
the button click will start the program.
My class code:-
Imports Microsoft
Imports System
Imports System.Net
Imports System.Data
Imports System.Windows
Imports System.Windows.Forms
Imports Excel = Microsoft.Office.Interop.Excel
Imports System.Collections.ObjectModel
Imports System.ComponentModel
Namespace URLValide
Public Class clsUrlCheck
Implements INotifyPropertyChanged
Public Event propertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
Public exclApplic As New Excel.Application
Public exclWkbOpe As Excel.Workbook
Public exclWksAct As Excel.Worksheet
Public exclRngUrl As Excel.Range
Public exclRngDes As Excel.Range
Public exclRngOut As Excel.Range
Public intMaxRow As Long
Public intCrtRow As Long
Private _strTotlOf As String
Private _strCrnUrl As String
Private _ColorIndx As String
Private _strPdfLst As ObservableCollection(Of String)
Private _strhdrPdf As ObservableCollection(Of String)
#Region "Region of poperties"
Public Property strTotlOf() As String
Get
Return _strTotlOf
End Get
Set(ByVal value As String)
_strTotlOf = value
Me.OnPropertyChanged("strTotlOf")
End Set
End Property
Public Property strCrnUrl() As String
Get
Return _strCrnUrl
End Get
Set(ByVal value As String)
_strCrnUrl = value
Me.OnPropertyChanged("strCrnUrl")
End Set
End Property
Public Property strPdfLst As ObservableCollection(Of String)
Get
Return _strPdfLst
End Get
Set(ByVal value As ObservableCollection(Of String))
_strPdfLst = value
Me.OnPropertyChanged("strPdfLst")
End Set
End Property
Public Property strhdrPdf As ObservableCollection(Of String)
Get
Return _strhdrPdf
End Get
Set(ByVal value As ObservableCollection(Of String))
_strhdrPdf = value
Me.OnPropertyChanged("strhdrPdf")
End Set
End Property
Public Property ColorIndx As String
Get
Return _ColorIndx
End Get
Set(ByVal value As String)
_ColorIndx = value
Me.OnPropertyChanged("ColorIndx")
End Set
End Property
Private Sub OnPropertyChanged(ByVal propertyName As String)
RaiseEvent propertyChanged(Me, New PropertyChangedEventArgs(propertyName))
End Sub
#End Region
#Region "function of Validating the URL's"
Public Function UrlCheck(ByVal strUrlReq As String)
Try
Dim WebReq As Net.HttpWebRequest = Net.HttpWebRequest.Create(strUrlReq)
WebReq.Method = "Head"
WebReq.Timeout = 5000
Using Response = WebReq.GetResponse()
Return True
End Using
Catch ex As Exception
ColorIndx = "True"
Return False
End Try
End Function
#End Region
#Region "Start Function"
Sub suStart()
Dim blnValid As Boolean
'strPdfLst.Clear()
'strPdfLst = makeList(exclRngUrl.Column, False)
If exclRngDes.Value = "Make Desc" Then
strPdfLst = makeList(exclRngUrl.Column, True)
exclRngDes.Delete()
Else
strPdfLst = makeList(exclRngUrl.Column, False)
End If
For Each exclRngEch As Excel.Range In exclRngUrl
strCrnUrl = exclRngEch.Text
strTotlOf = exclRngEch.Row & "OF" & intMaxRow
blnValid = UrlCheck(exclRngEch.Value.ToString)
If blnValid Then
exclWksAct.Cells(exclRngEch.Row, exclRngOut.Column).value = "Web Page Present"
Else
exclWksAct.Cells(exclRngEch.Row, exclRngOut.Column).value = "Web Page Error"
End If
Next
End Sub
Function makeList(ByVal intColNum As Long, ByVal blnMkeStr As Boolean) As ObservableCollection(Of String)
Dim ObsColTem As ObservableCollection(Of String) = New ObservableCollection(Of String)
If Not blnMkeStr Then
For intLopCnt As Int32 = intCrtRow To intMaxRow
ObsColTem.Add(exclWksAct.Cells(intLopCnt, intColNum).Text)
Next
Else
For intLopCnt As Int32 = intCrtRow To intMaxRow
Dim strDesc As String = Mid(exclWksAct.Cells(intLopCnt, intColNum).Text, InStrRev(exclWksAct.Cells(intLopCnt, intColNum).Text, "/", , CompareMethod.Text) + 1)
ObsColTem.Add(strDesc)
Next
End If
Return ObsColTem
End Function
#End Region
End Class
End Namespace
This is from working code
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=RowSelected}" Value="True">
<Setter Property="Background" Value="Gainsboro" />
<Setter Property="FontWeight" Value="Bold" />
</DataTrigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
create a converter which takes the link as parameter and send the background/foreground color, the converters checks the link and sends the correct code accordingly,bind the color code to the itemtemplate background/foreground property.
First create a Broken-Property which you can bind to and then just create a Style for ListViewItems with a DataTrigger on the Broken-Property!
<Style TargetType="{x:Type ListViewItem}">
<Style.Triggers>
<DataTrigger Binding="{Binding Broken}" Value="True">
<Setter Property="Background" Value="Red"/>
<Setter Property="Foreground" Value="White"/>
</DataTrigger>
</Style.Triggers>
</Style>
Have not tested this code but it should work!

Binding from an XAML resource dictionary to a class property

I am having a very difficult time setting up a binding which I think should be easy. Help is greatly appreciated.
I have a resource dictionary named FormResource.xaml. In this dictionary contains a Style for the ScrollView that I redine the template for. The purpose is I want a wider vertical scrollbar on it.
<Style x:Key="LargeScrolling" TargetType="ScrollViewer">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ScrollViewer">
<Grid Background="{TemplateBinding Background}">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ScrollContentPresenter x:Name="ScrollContentPresenter"
Margin="{TemplateBinding Padding}"
ContentTemplate="{TemplateBinding ContentTemplate}"/>
<ScrollBar x:Name="PART_VerticalScrollBar"
Style="{StaticResource LargeVerticalScrollBar}"
Width="{Binding ElementName=MDTForm, Path=ScrollBarWidth}"
IsTabStop="False"
Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"
Grid.Column="1" Grid.Row="0" Orientation="Vertical"
ViewportSize="{TemplateBinding ViewportHeight}"
Maximum="{TemplateBinding ScrollableHeight}"
Minimum="0"
Value="{TemplateBinding VerticalOffset}"
Margin="0,-1,-1,-1"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I have a UserControl named FormControl.
public class FormControl : UserControl
I used to have this as a partial class with a XAML componenet, in which what I am trying to do worked, but I had to remove the XAML since I derive from this class in another assembly and WPF does not allow you to derive from a partial class in another assembly.
In FormControl I define a ScrollBarWidth property.
public static readonly DependencyProperty ScrollBarWidthProperty = DependencyProperty.Register("ScrollBarWidth", typeof(double), typeof(FormControl));
public double ScrollBarWidth
{
get { return (double)base.GetValue(ScrollBarWidthProperty); }
set { base.SetValue(ScrollBarWidthProperty, value); }
}
When I had this as a partial class in the main declaration I gave the FormControl class a Name of MDTForm, which is what I am using as the ElementName in my binding. I tried registering this name in FormClass.cs but no matter what I do the scrollbar is not picking up the property value.
Here is where I create my ScrollViewer in the FormControl class.
_canvasScrollViewer = new ScrollViewer();
_canvasScrollViewer.VerticalScrollBarVisibility = ScrollBarVisibility.Auto;
_canvasScrollViewer.VerticalAlignment = VerticalAlignment.Top;
_canvasScrollViewer.MaxHeight = Constants.ScrollViewMaxHeight;
_canvasScrollViewer.Style = (Style)FindResource("LargeScrolling");
The only way that I got this to work was to bind to a static property. I used this for the binding.
Width="{Binding Source={x:Static form:FormControl.ScrollBarWidthP}}"
Then defined the property as such.
public static double ScrollBarWidth { get; set; }
However, I don't want this as I can have multiple FormControl objects loaded at the same time and they may not all have the same scroll bar width property.
Use a RelativeSource Binding instead of ElementName:
{Binding RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType={x:Type controls:FormControl}}, Path=ScrollBarWidth}
This will walk up the visual tree at runtime to find the parent control containing the ScrollViewer, which solves both your scoping and multiple instance issues.

WPF popup: how to make a reusable template for popups?

Since Popup doesn't derive from Control and doesn't have a template, how can I define a template so that all popups look the same? I need to design one that has a certain look and don't want to have to copy markup each time one is used.
This seems pretty easy but I can't figure out how to do it. The Child property defines a logical tree but I don't see how you can pull that out into a template and reuse it.
I was looking to do the same thing and here is what I came up with:
I inherited from ContentPresenter, styled that control as I wanted and than placed the derived ContentPresenter inside my Popup, I only used 2 text blocks for the simplicity but it is easy to understand how any content could be added.
My custom control:
using System.Windows;
using System.Windows.Controls;
namespace CustomControls
{
[TemplatePart(Name = PART_PopupHeader, Type = typeof(TextBlock))]
[TemplatePart(Name = PART_PopupContent, Type = typeof(TextBlock))]
public class CustomPopupControl : ContentControl
{
private const string PART_PopupHeader = "PART_PopupHeader";
private const string PART_PopupContent = "PART_PopupContent";
private TextBlock _headerBlock = null;
private TextBlock _contentBlock = null;
static CustomPopupControl()
{
DefaultStyleKeyProperty.OverrideMetadata
(typeof(CustomPopupControl),
new FrameworkPropertyMetadata(typeof(CustomPopupControl)));
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
_headerBlock = GetTemplateChild(PART_PopupHeader) as TextBlock;
_contentBlock = GetTemplateChild(PART_PopupContent) as TextBlock;
}
public static readonly DependencyProperty HeaderTextProperty =
DependencyProperty.Register("HeaderText", typeof(string), typeof(CustomPopupControl), new UIPropertyMetadata(string.Empty));
public string HeaderText
{
get
{
return (string)GetValue(HeaderTextProperty);
}
set
{
SetValue(HeaderTextProperty, value);
}
}
public static readonly DependencyProperty ContentTextProperty =
DependencyProperty.Register("ContentText", typeof(string), typeof(CustomPopupControl), new UIPropertyMetadata(string.Empty));
public string ContentText
{
get
{
return (string)GetValue(ContentTextProperty);
}
set
{
SetValue(ContentTextProperty, value);
}
}
}
}
Style for the control:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CustomControls">
<Style TargetType="{x:Type local:CustomPopupControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:CustomPopupControl}">
<Border CornerRadius="3" BorderThickness="1" BorderBrush="White">
<Border.Background>
<SolidColorBrush Color="#4b4b4b" Opacity="0.75"/>
</Border.Background>
<Border.Effect>
<DropShadowEffect ShadowDepth="0"
Color="White"
Opacity="1"
BlurRadius="5"/>
</Border.Effect>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock Text="{TemplateBinding HeaderText}"
Grid.Row="0"
Foreground="#5095d6"
FontWeight="Bold"
VerticalAlignment="Bottom"
Margin="{TemplateBinding Margin}"
HorizontalAlignment="Left"/>
<Rectangle Grid.Row="1" Stroke="AntiqueWhite" Margin="1 0"></Rectangle>
<TextBlock Grid.Row="2"
Grid.ColumnSpan="2"
x:Name="PART_TooltipContents"
Margin="5, 2"
Text="{TemplateBinding ContentText}"
TextWrapping="Wrap"
MaxWidth="200"/>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The use of the control:
<StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Center">
<Button x:Name="Button1" Content="Button with popup" HorizontalAlignment="Center">
</Button>
<Button x:Name="Button2" Content="Another button with popup" HorizontalAlignment="Center">
</Button>
<Popup IsOpen="True"
FlowDirection="LeftToRight"
Margin="10"
PlacementTarget="{Binding ElementName=Button1}"
Placement="top"
StaysOpen="True">
<local2:CustomPopupControl HeaderText="Some Header Text" ContentText="Content Text that could be any text needed from a binding or other source" Margin="2">
</local2:CustomPopupControl>
</Popup>
<Popup IsOpen="True"
FlowDirection="LeftToRight"
Margin="10"
PlacementTarget="{Binding ElementName=Button2}"
Placement="Bottom"
StaysOpen="True">
<local2:CustomPopupControl HeaderText="Different header text" ContentText="Some other text" Margin="2">
</local2:CustomPopupControl>
</Popup>
</StackPanel>
I tried illustrating how some properties can be constant across all controls, others can be customized per control and others could be bound to TemplatePart, here is the final result:
Depends how you want your pop-ups to behave. If they're just for displaying information in a uniform manner, than you might want to have a class that derives from Window that has the standard formats and styling wrapped around a ContentPresenter then bind the content of the presenter to a property which can represent the custom information for each pop-up.
Then its just a matter of programatically inserting whatever custom content you want before displaying the pop-up window.
Hope it helps.

Binding Silverlight UserControl custom properties to its' elements

I'm trying to make a simple crossword puzzle game in Silverlight 2.0. I'm working on a UserControl-ish component that represents a square in the puzzle. I'm having trouble with binding up my UserControl's properties with its' elements. I've finally (sort of) got it working (may be helpful to some - it took me a few long hours), but wanted to make it more 'elegant'.
I've imagined it should have a compartment for the content and a label (in the upper right corner) that optionally contains its' number. The content control probably be a TextBox, while label control could be a TextBlock. So I created a UserControl with this basic structure (the values are hardcoded at this stage):
<UserControl x:Class="XWord.Square"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
FontSize="30"
Width="100" Height="100">
<Grid x:Name="LayoutRoot" Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock x:Name="Label" Grid.Row="0" Grid.Column="1"
Text="7"/>
<TextBox x:Name="Content" Grid.Row="1" Grid.Column="0"
Text="A"
BorderThickness="0" />
</Grid>
</UserControl>
I've also created DependencyProperties in the Square class like this:
public static readonly DependencyProperty LabelTextProperty;
public static readonly DependencyProperty ContentCharacterProperty;
// ...(static constructor with property registration, .NET properties
// omitted for brevity)...
Now I'd like to figure out how to bind the Label and Content element to the two properties. I do it like this (in the code-behind file):
Label.SetBinding( TextBlock.TextProperty, new Binding { Source = this, Path = new PropertyPath( "LabelText" ), Mode = BindingMode.OneWay } );
Content.SetBinding( TextBox.TextProperty, new Binding { Source = this, Path = new PropertyPath( "ContentCharacter" ), Mode = BindingMode.TwoWay } );
That would be more elegant done in XAML. Does anyone know how that's done?
First, set the DataContext on the UserControl using {RelativeSource Self}:
<UserControl x:Class="XWord.Square"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
FontSize="30"
Width="100" Height="100"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
Now you can bind the individual elements to the properties of the usercontrol:
<TextBlock x:Name="Label" Grid.Row="0" Grid.Column="1"
Text="{Binding LabelText}"/>
<TextBox x:Name="Content" Grid.Row="1" Grid.Column="0"
Text="{Binding ContentCharacter}" BorderThickness="0" />
For SL 2.0, you'll need to set the DataContext on the UserControl's Loaded event handler.
private void UserControl_Loaded( object sender, RoutedEventArgs e ) {
LayoutRoot.DataContext = this;
}
As Silverlight cannot use FindAncestor technique you can use a trick similar to the one that sets the UserControl's name, but without breaking its functionality by using the name of the LayoutRoot...
<UserControl x:Class="XWord.Square"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
FontSize="30"
Width="100" Height="100">
<Grid x:Name="LayoutRoot" Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock x:Name="{Binding Path=Parent.LabelText, ElementName=LayoutRoot}" Grid.Row="0" Grid.Column="1"
Text="7"/>
<TextBox x:Name="{Binding Path=Parent.ContentCharacter, ElementName=LayoutRoot}" Grid.Row="1" Grid.Column="0"
Text="A"
BorderThickness="0" />
</Grid>
</UserControl>
It worked in SL3 without having to add any additional code (I'm using it in a WP7 app), but don't know if you can use it in SL2. Well, I realize now how this question is old, hope it's still helpful, I've arrived here because the answers I got for the same problem in WP7 didn't convince me.
I think you are looking for UI Element to Element Binding which is a feature of Silverlight 3.
I may not be understanding your issue exactly. In Silverlight, you are able to bind to almost any data object. So, if you have a PuzzleSquare class that contains properties Content and Label, you may bind to these properties directly from the object.
Let's say you created a simple object PuzzleSquare:
public class PuzzleSquare
{
public string Content{ get; set; }
public string Label{ get; set; }
public void PuzzleSquare(){};
public void PuzzleSquare(string label, string content):this()
{
Content = content;
Label = label;
}
}
So, if you are building the app with the classic view/code behind model, your code behind would add this object to the DataContext property of the grid on page load:
LayoutRoot.DataContext = new PuzzleSquare("1", "A");
Your Xaml would bind to the Square property:
<TextBlock x:Name="Label" Grid.Row="0" Grid.Column="1"
Text="{Binding Label}"/>
<TextBox x:Name="Content" Grid.Row="1" Grid.Column="0"
Text="{Binding Content}" BorderThickness="0" />
Does that make sense?
ib.
This worked in Silverlight 4.0
Put a name on the UserControl, and then refer to it in the TextBlock
<UserControl x:Class="XWord.Square"
...omitted for brevity ...
x:Name="Square">
<TextBlock x:Name="Label" ...
Text="{Binding Path=LabelText,ElementName=Square}"/>
Try this:
Public ReadOnly TextProperty As DependencyProperty = DependencyProperty.Register("Text", GetType(String), GetType(ButtonEdit), New System.Windows.PropertyMetadata("", AddressOf TextPropertyChanged))
Public Property Text As String
Get
Return GetValue(TextProperty)
End Get
Set(ByVal value As String)
SetValue(TextProperty, value)
End Set
End Property
Private Sub TextPropertyChanged()
If String.IsNullOrEmpty(Text) Then
TextBox1.Text = ""
Else
TextBox1.Text = Text
End If
End Sub
Private Sub TextBox1_LostFocus(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles TextBox1.LostFocus
Text = TextBox1.Text
End Sub
I can bind in both XAML and code behind.

Resources