Why Canvas.SetTop animation doesn't work properly? - wpf

I have this xaml:
<Canvas Width="75" Height="75">
<Button x:Name="button" Background="Olive" Canvas.Left="0" Canvas.Top="0" Width="75" Height="75" Click="button_Click"/>
</Canvas>
And this code behind:
Private Sub button_Click(ByVal sender as Object, ByVal e as System.Windows.RoutedEventArgs)
Canvas.SetTop(sender, -75)
Dim sb1 As New Storyboard
Dim da1 As New DoubleAnimationUsingKeyFrames
da1.BeginTime = TimeSpan.FromSeconds(0)
Storyboard.SetTargetName(da1, CType(sender, Button).Name)
Storyboard.SetTargetProperty(da1, New PropertyPath(Canvas.TopProperty))
Dim t1 As Double = Canvas.GetTop(sender)
da1.KeyFrames.Add(New SplineDoubleKeyFrame(t1 + 75, TimeSpan.FromSeconds(0.2)))
sb1.Children.Add(da1)
BeginStoryboard(sb1)
End Sub
When I click the button the first time, it properly goes up by 75 and animates back to 0, but when I click the button again, it just animates down by 75. Why is it skipping the Canvas.SetTop line and goes straight to the animating part? And how to fix this?

Use this code (it is in C#) before Canvas.SetTop
(sender as UIElement).BeginAnimation(Canvas.TopProperty, null);
This will avoid that any animation overrides the value Canvas.TopProperty
This link will help you
http://joshsmithonwpf.wordpress.com/2008/08/21/removing-the-value-applied-by-an-animation/

Related

Odd Scrollbar behaviour in WPF control

I have made the following simple control, which I add to another window as a popup (starts hidden, gets changed to visible on a button click)
<UserControl x:Class="AddGroupsCtrl"
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:local="clr-namespace:ASManager2017"
mc:Ignorable="d" d:DesignWidth="255" Height="413">
<GroupBox x:Name="groupBox" Header=" Active Directory Groups" HorizontalAlignment="Stretch" Margin="0,0,0,0" VerticalAlignment="Stretch" Height="350" Width="233" BorderBrush="{DynamicResource {x:Static SystemColors.ActiveBorderBrushKey}}">
<Grid Height="auto">
<ListBox x:Name="grouplistBox" HorizontalAlignment="Stretch" Height="auto" Margin="0,0,0,0" VerticalAlignment="Stretch" Width="auto" SelectionMode="Extended" ScrollViewer.VerticalScrollBarVisibility="Visible" Background="{DynamicResource fadeBrush}"/>
<Button x:Name="addButton" Content="Add" HorizontalAlignment="Right" Margin="0,0,22,0" VerticalAlignment="Bottom" Width="75"/>
<Button x:Name="button" Content="X" HorizontalAlignment="Right" Margin="0,0,22,0" VerticalAlignment="Top" Width="20" Height="20" Background="{DynamicResource {x:Static SystemColors.ControlLightLightBrushKey}}"/>
</Grid>
</GroupBox>
In the code behind this I have the following fragment....
For Each grp As String In gsList
grouplistBox.Items.Add(grp)
Next
Everything seems to work fine, apart from the scroll bar at the side of the listbox. This starts at about half the height of the entire control, and when trying to slide it down the list doesn't scroll, but the scroller shrinks in size until it gets to a small bar, and then starts scrolling to contents of the window. Likewise dragging the bar back up: the listbox will get to the top of the list when the bar is about halfway up the scroll-area, and then the bar will expand.
Can anyone help me correct this behaviour/explain what I am doing wrong?
Thanks.
Pete.
After more experimenting, things are getting weirder....
Imports AshbyTools
Imports System.DirectoryServices.AccountManagement
Imports System.ComponentModel
Public Class AddGroupsCtrl
Dim _domainString As String
Dim _ouString As String
Public Event addClicked(ByVal glist As List(Of String))
<Description("ouString"), DisplayName("OU String"), Category("Data")>
Public Property ouString As String
Get
Return _ouString
End Get
Set(value As String)
_ouString = value
End Set
End Property
<Description("domainString"), DisplayName("Domain String"), Category("Data")>
Public Property domainString As String
Get
Return _domainString
End Get
Set(value As String)
_domainString = value
End Set
End Property
Private Sub button_Click(sender As Object, e As RoutedEventArgs) Handles button.Click
Me.Visibility = Visibility.Hidden
End Sub
Public Sub loadGroups()
grouplistBox.Items.Clear()
Dim groupCTX As PrincipalContext = ADTools.getConnection(domainString, ouString)
Dim gList As List(Of GroupPrincipal) = ADTools.getManagedGroups(groupCTX)
Dim gsList As New List(Of String)
For Each grp As GroupPrincipal In gList
If Not (grp.DistinguishedName.Contains("Staff Groups") Or grp.DistinguishedName.Contains("Subject Groups") Or grp.DistinguishedName.Contains("Tutor Groups")) Then
gsList.Add(grp.DisplayName)
End If
Next
'For n As Integer = 1 To 70
' grouplistBox.Items.Add("item" & n)
'Next
gsList.Sort()
For Each grp As String In gsList
grouplistBox.Items.Add(grp)
Next
End Sub
Private Sub addButton_Click(sender As Object, e As RoutedEventArgs) Handles addButton.Click
Dim ret As New List(Of String)
For Each grp In grouplistBox.SelectedItems
ret.Add(grp.ToString)
Next
RaiseEvent addClicked(ret)
End Sub
End Class
Upon loadGroups() if I replace the
For Each grp As String In gsList
grouplistBox.Items.Add(grp)
Next
with the commented out code, the scrollbar works perfectly.
With the list of strings from gsList, I get the odd behaviour.
I could post the entire project, but since it is hard-coded for our active directory structure it wouldn't compile on another system. (also, as I am just using this to learn WPF and it's an internal tool, I've hard-coded numerous passwords)
Ok, I have solved the issue. And the answer is even more confusing. Turns out that in the code, where I got the DisplayName of the group to add to the list of string, it was returning 'Nothing' for each of them. Yet somehow displayed the list correctly (although with a screwy scrollbar). Now I have changed it to return grp.name rather than displayname, and EVERYTHING works as I'd expect.

How do I find the image in a WPF Datagrid ColumnHeader so I can change the image?

I'm attempting to implement Excel-like column filtering and sorting. To do this, I used a DataTemplate to define the Column Header.
<DataGrid x:Name="dataGrid" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" CanUserSortColumns="False">
<DataGrid.Resources>
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="23"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button x:Name="ExcelFilterButton" Tag="{Binding}" Click="ExcelFilterButton_Click" Margin="0,0,0,0" BorderThickness="0" Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}" Focusable="False" Grid.Column="0">
<Image Source="Resources\NoSortNoFilter.png" Width="19" Height="19" />
</Button>
<TextBlock Text="{Binding}" HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="1" />
</Grid>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</DataGrid.Resources>
</DataGrid>
And it comes out nicely.
I tried using VisualTreeHelper to find the image from the Column Header, but the Header property is a string. I've tried using the HeaderStyle and HeaderTemplate properties also but to no avail.
Using a WPF Spy program called Snoop, I can see the image in there, but still can't figure out how to access it in code. The reason I need to access it in code is to change the image based on whether that column is sorted and/or filtered. (Could this be done in XAML?)
Ok, I figured out how to do it. This most likely not the right way to do it, but I found a way that works.
To give you a little about the process.
The user clicks a header button. The buttons Tag property is bound to the column header.
The click event handler instantiates the context menu and sets its Tag to equal the button Tag.
The user clicks on a menu item.
The event handler sends the Context Menu Tag property and image name to the routine that finds the button, and then the image in the button, and changes the image.
now for the code.
The button click event handler:
Private Sub ExcelFilterButton_Click(sender As Object, e As RoutedEventArgs)
With DirectCast(Resources("sortContextMenu"), ContextMenu)
.Tag = DirectCast(sender, Button).Tag
.IsOpen = True
End With
End Sub
The menu item click event handler
Private Sub ContextMenuItem_Click(Sender As Object, e As RoutedEventArgs)
If TypeOf Sender Is MenuItem Then
'just testing, of course this isn't all this handler does.
SetColumnSortImage(Sender.Tag, "Filtered")
End If
End Sub
The SetColumnSortImage routine, which calls the two following routines.
Private Sub SetColumnSortImage(Tag As String, ImageName As String)
Dim btn As Button = Nothing
GetSortButton(Of Button)(dataGrid, Tag, btn)
If btn IsNot Nothing Then
Dim img As Image = GetChildOfType(Of Image)(btn)
img.Source = New BitmapImage(New Uri("pack://application:,,,/Resources/" & ImageName & ".png"))
End If
End Sub
The GetSortButton routine
Private Sub GetSortButton(Of T As DependencyObject)(dep As DependencyObject, Tag As String, ByRef out As DependencyObject)
If dep IsNot Nothing Then
If TypeOf dep Is Button AndAlso CType(dep, Button).Tag = Tag Then
out = dep
Else
If VisualTreeHelper.GetChildrenCount(dep) > 0 Then
For i As Integer = 0 To VisualTreeHelper.GetChildrenCount(dep) - 1
GetSortButton(Of T)(VisualTreeHelper.GetChild(dep, i), Tag, out)
Next
End If
End If
End If
End Sub
This routine was found elsewhere on StackOverflow in C#. I converted it to VB.
Private Function GetChildOfType(Of T As DependencyObject)(depObj As DependencyObject) As T
If depObj Is Nothing Then
Return Nothing
End If
For i As Integer = 0 To VisualTreeHelper.GetChildrenCount(depObj) - 1
Dim child = VisualTreeHelper.GetChild(depObj, i)
Dim result = If(TryCast(child, T), GetChildOfType(Of T)(child))
If result IsNot Nothing Then
Return result
End If
Next
Return Nothing
End Function
You may have a better way. Please post if you do.

Image not shown in 1st col Listview WPF with VB.NET (1st Col Image, 2nd Col String)

I need expert help on my project.
Please help me, I am newbie to WPF, I am using VB.NET to create application to show pictures from folder chosen by user. on Form I put Button (press to choose folder), Image (to show image chosen from ListView), ListView (2 columns with 1st column image thumbnail and 2nd column the filename).
Please check my XAML code below :
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:System="clr-namespace:System;assembly=mscorlib" x:Class="MainWindow"
Title="MainWindow" Height="448.545" Width="698.135">
<Grid>
<Image x:Name="ImgView" Margin="259,44,10,72"/>
<Button Content="Pilih Folder" HorizontalAlignment="Left" Height="29" Margin="10,10,0,0" VerticalAlignment="Top" Width="92" Click="Button_Click"/>
<ListView x:Name="ListView1" HorizontalAlignment="Left" Height="351" Margin="10,44,0,0" VerticalAlignment="Top" Width="244">
<ListView.View>
<GridView>
<GridViewColumn Header="Gbr" DisplayMemberBinding="{Binding Gambar}"/>
<GridViewColumn Header="Nama File" DisplayMemberBinding="{Binding NamaFile}"/>
</GridView>
</ListView.View>
</ListView>
</Grid>
</Window>
And here is my Code-behind
Imports System.Windows.Forms
Imports System.Collections.ObjectModel
Class MainWindow
Private _GbrCollection As New ObservableCollection(Of GambarCol)
Public ReadOnly Property GbrCollection() As ObservableCollection(Of GambarCol)
Get
Return _GbrCollection
End Get
End Property
Private Sub MainWindow_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
InitializeComponent()
End Sub
Private Sub Button_Click(sender As Object, e As RoutedEventArgs)
Dim ImgList() As Image
Dim Img88 As Image
Dim fld As New FolderBrowserDialog
fld.RootFolder = Environment.SpecialFolder.Desktop
'fldDialog.RootFolder = Environment.SpecialFolder.Desktop;
fld.ShowDialog()
'txtPath.Text = fld.SelectedPath
'filesListBox.Items.Clear()
Dim fileNames = My.Computer.FileSystem.GetFiles(fld.SelectedPath, FileIO.SearchOption.SearchTopLevelOnly, "*.jpg")
'Debug.WriteLine(fileNames.Count)
ReDim ImgList(fileNames.Count)
For Each fileName As String In fileNames
_GbrCollection.Add(New GambarCol(Img88, fileName))
Next
ListView1.ItemsSource = GbrCollection
End Sub
Private Sub ListView1_MouseDoubleClick(sender As Object, e As MouseButtonEventArgs) Handles ListView1.MouseDoubleClick
Dim ImgShow As New Image
If ListView1.SelectedItems.Count > 0 Then
End If
'ImgShow.Source = New BitmapImage(New System.Uri(ListView1.Items))
End Sub
Private Sub ListView1_SelectionChanged(sender As Object, e As SelectionChangedEventArgs) Handles ListView1.SelectionChanged
End Sub
End Class
Public Class GambarCol
Private _Gambar As Image
Private _NamaFile As String
Public ReadOnly Property Gambar() As Image
Get
_Gambar = New Image
_Gambar.Source = New BitmapImage(New System.Uri(NamaFile))
_Gambar.Height = 60
Return _Gambar
End Get
End Property
Public ReadOnly Property NamaFile() As String
Get
Return _NamaFile
End Get
End Property
Public Sub New(ByVal GbrImg As Image, ByVal NamaFileNF As String)
_Gambar = GbrImg
_NamaFile = NamaFileNF
End Sub
End Class
Master, help me solve 3 problems :
1. Image can't be shown in column 1 in Listview
2. How to get value from column 2 when user double click the selected row
3. I know my code too complicated , can someone help me to make it simple
Really Really need help
Thank you very much
I just found out the solution, after several references to other articles, this is how I did it.
The XAML code built on StackPanel to hold Image for first col, and second col as usual
<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="409.574" Width="580.224">
<Grid>
<ListView x:Name="ListView1" VirtualizingStackPanel.IsVirtualizing="True" ItemsSource="{Binding ListViewItemsCollections}" Margin="0,56,0,10" HorizontalAlignment="Left" Width="228">
<ListView.View>
<GridView AllowsColumnReorder="False">
<GridViewColumn x:Name="GridViewColumnName" Header="Picture" Width="90">
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image x:Name="Image_GridViewColumnName" Width="90" Height="50" Source="{Binding GridViewColumnNameImageSource}" />
<Label Content="{Binding GridViewColumnNameLabelContent}" Width="50" Height="50" />
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn x:Name="GridViewColumnLocation" Header="Location" Width="150" DisplayMemberBinding="{Binding GridViewColumnLocation}" />
</GridView>
</ListView.View>
</ListView>
<Button x:Name="btnFolder" Content="Pilih Folder" Margin="10,10,0,0" Height="41" VerticalAlignment="Top" HorizontalAlignment="Left" Width="77"/>
<TextBox x:Name="txtPath" Height="23" Margin="112,10,0,0" TextWrapping="Wrap" VerticalAlignment="Top" HorizontalAlignment="Left" Width="116"/>
<Image x:Name="ImgView" Margin="247,56,10,113"/>
</Grid>
</Window>
And for the code, just use Add method with NEW key, frankly I still don't understand the concept behind New, since WPF real new to me, VB.NET still not all 100% I can code.
For code-behind as follow
Imports System.Windows.Forms.ListViewItem.ListViewSubItemCollection
Imports System.IO
Imports System.Windows.Window
Imports System.Windows.Forms
Imports System.Windows.Forms.FolderBrowserDialog
Class MainWindow
Dim IsiFile() As String
Private Sub btnFolder_Click(sender As Object, e As RoutedEventArgs) Handles btnFolder.Click
Dim fld As New FolderBrowserDialog
Dim iCnt As Integer = 0
fld.RootFolder = Environment.SpecialFolder.Desktop
fld.ShowDialog()
txtPath.Text = fld.SelectedPath
Dim fileNames = My.Computer.FileSystem.GetFiles(fld.SelectedPath, FileIO.SearchOption.SearchTopLevelOnly, "*.jpg")
ReDim IsiFile(fileNames.Count)
For Each fileName As String In fileNames
ListView1.Items.Add(New With { _
Key .GridViewColumnLocation = fileName, _
Key .GridViewColumnNameImageSource = fileName _
})
IsiFile(iCnt) = fileName
iCnt += 1
Next
End Sub
Private Sub ListView1_MouseDoubleClick(sender As Object, e As MouseButtonEventArgs) Handles ListView1.MouseDoubleClick
Dim Gambar As New BitmapImage
Gambar.BeginInit()
Gambar.UriSource = New Uri(IsiFile(ListView1.SelectedIndex))
Gambar.EndInit()
ImgView.Source = Gambar
End Sub
End Class
I hope this helps , thank you

WPF: Placing a textbox randomly on a canvas

I have a canvas of sorts derived from a 'Panel' used for custom drawing of lines and other geometries, all from VB code. I got this approach from a book and I'm not sure it's the best approach. The drawing part works so far for me.
But what I need is to put a textbox control on the control containing text which can be edited by the user. The textbox needs to be placed at coordinates determined dynamically and later deleted. There will probably be other controls handled so.
The following code does nothing:
tb = New TextBox()
tb.Text = "How now brown cow?"
tb.BorderThickness = New Thickness(3)
tb.BorderBrush = Brushes.CadetBlue
drawingSurface.Children.Add(tb)
This is the definition of my DrawingCanvas:
Public Class DrawingCanvas
Inherits Panel
Private visuals As New List(Of Visual)()
Private hits As New List(Of DrawingVisual)()
Protected Overrides Function GetVisualChild(ByVal index As Integer) As Visual
Return visuals(index)
End Function
Protected Overrides ReadOnly Property VisualChildrenCount() As Integer
Get
Return visuals.Count
End Get
End Property
Public Sub AddVisual(ByVal visual As Visual)
visuals.Add(visual)
MyBase.AddVisualChild(visual)
MyBase.AddLogicalChild(visual)
End Sub
Public Sub DeleteVisual(ByVal visual As Visual)
visuals.Remove(visual)
MyBase.RemoveVisualChild(visual)
MyBase.RemoveLogicalChild(visual)
End Sub
Public Function GetVisual(ByVal point As Point) As DrawingVisual
Dim hitResult As HitTestResult = VisualTreeHelper.HitTest(Me, point)
Return TryCast(hitResult.VisualHit, DrawingVisual)
End Function
Public Function GetVisuals(ByVal region As Geometry) As List(Of DrawingVisual)
hits.Clear()
Dim parameters As New GeometryHitTestParameters(region)
Dim callback As New HitTestResultCallback(AddressOf Me.HitTestCallback)
VisualTreeHelper.HitTest(Me, Nothing, callback, parameters)
Return hits
End Function
Private Function HitTestCallback(ByVal result As HitTestResult) As HitTestResultBehavior
Dim geometryResult As GeometryHitTestResult = CType(result, GeometryHitTestResult)
Dim visual As DrawingVisual = TryCast(result.VisualHit, DrawingVisual)
If visual IsNot Nothing AndAlso geometryResult.IntersectionDetail = IntersectionDetail.FullyInside Then
hits.Add(visual)
MsgBox("Ouch")
End If
Return HitTestResultBehavior.Continue
End Function
End Class
Here is the XAML. I added a textbox to the DrawingCanvas just to see if something appears. Nothing did. In fact, I want to do this in code, not XAML. I thought I could hide or move it around dynamically.
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Music"
Title="MainWindow" Height="539" Width="892">
<DockPanel>
<Menu DockPanel.Dock="Top" Name="MainMenu" VerticalAlignment="Top" Height="25">
<MenuItem Name="File" Header="File">
<MenuItem Name="Open" Header="Bla bla..."/>
</MenuItem>
</Menu>
<local:DrawingCanvas DockPanel.Dock="Bottom" x:Name="drawingSurface" RenderTransformOrigin="0.5,0.5" >
<TextBox Height="0" Name="TextBox1" Width="45" Text="How now brown cow?" />
</local:DrawingCanvas>
</DockPanel>
</Window>
Thanks for helping a nooby. A solution would be very useful for me. This was easy with windows forms, but I need the drawing speed of WPF.
I think you are a bit off here. In WPF you have a control called Canvas. I would suggest you use that instead of your own "DrawingCanvas", which I can't get to work btw. :( (For some reason I cant create code blocks so if someone can edit it I would be pleased)
Anyhow,
<local:DrawingCanvas DockPanel.Dock="Bottom" x:Name="drawingSurface" RenderTransformOrigin="0.5,0.5" >
<TextBox Height="0" Name="TextBox1" Width="45" Text="How now brown cow?" />
</local:DrawingCanvas>
Turns into:
<Canvas x:Name="drawingSurface">
</Canvas>
And then to add a textbox just do as your current code:
Dim tb as New TextBox
drawingSurface.Children.Add(tb)
This should give you what you need.
Heres the code for adding a rectangle to your canvas.
Private Sub DrawBackground()
Dim Rect As New Rectangle()
Rect.Height = 50
Rect.Width = 50
Rect.Fill = Brushes.Cornsilk
drawingSurface.SetTop(Rect, 30)
drawingSurface.SetLeft(Rect, 100)
drawingSurface.Children.Add(Rect)
End Sub
I'll add another answer that might be more in the line of what you are looking for. This is a class that inherits from Canvas that will allow you to draw stuff in the same way as say you do in your comment.
I also creates a textbox on a random location when it is created.
Public Class DrawingCanvas
Inherits Canvas
Public RandomTextBox As New TextBox
Protected Overrides Sub OnRender(dc As System.Windows.Media.DrawingContext)
Dim brush As Brush = Brushes.Black
Dim drawingPen As Pen = New Pen(Brushes.Green, 3)
dc.DrawRectangle(brush, drawingPen, New Rect(5, 5, Me.ActualWidth - 5, Me.ActualHeight - 5))
RandomTextBox.Text = "Herpdiderp"
If Not Me.Children.Contains(RandomTextBox) Then
Dim r As New Random()
RandomTextBox.Height = 23
RandomTextBox.Width = 100
Me.SetTop(RandomTextBox, r.Next(0, Me.ActualHeight - RandomTextBox.Height))
Me.SetLeft(RandomTextBox, r.Next(0, Me.ActualWidth - RandomTextBox.Width))
Me.Children.Add(RandomTextBox)
End If
End Sub
End Class
This is not a full answer. #WozzeC, you were right about using the canvas - almost.
I have managed to solve this in xaml alone - I want to eventually solve it in vb.net.
<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>
<DockPanel HorizontalAlignment="Stretch" Name="DockPanel1" VerticalAlignment="Stretch" >
<Menu Height="23" DockPanel.Dock="Top" Name="Menu1" VerticalAlignment="Top" />
<Canvas Name="Canvas1" Background="Aquamarine">
<TextBox Canvas.Left="118" HorizontalScrollBarVisibility="Disabled" Canvas.Top="81" AcceptsReturn="True" Height="auto" Name="TextBox1" Width="68" Text="Herpdiderp" BorderThickness="0" Background="Aquamarine" />
</Canvas>
</DockPanel>
</Grid>
And here is a piece of code that expands the text as needed. I think it's almost totally cool. It expands both to the right and downwards, as if you're actually typing on the form. It adds a little too much on the right, but it's not visible in this version because the background color is the same.
Here is the event code that expands it to the right.
Imports System.Globalization
Class MainWindow
Private Sub TextBox1_TextChanged(sender As System.Object, e As System.Windows.Controls.TextChangedEventArgs) Handles TextBox1.TextChanged
Dim ft As New FormattedText(TextBox1.Text, CultureInfo.GetCultureInfo("en-us"), FlowDirection.LeftToRight, New Typeface("Verdana"), 16, Brushes.Black)
TextBox1.Width = ft.Width
End Sub
End Class
I tried this with my existing solution and the textbox does not appear. I made the DrawingCanvas into a plain Canvas and commented out all the code referring to the DrawingCanvas. And the textbox does appear. The problem is this: I need the functionality in the DrawingCanvas - which derives from Canvas. But because the baseclass methods are Protected, I can't get to them. I can only use them in a derived class, unless there is another way I don't know about.
Any ideas about how to solve this?

Filtering listbox based on textbox text in WPF

I was wondering if I could get some help with this one.
I'm using a dataset containing 2 tables (dbo.Project, and dbo.Materials) and collectionview to display data into a listbox.
I need to filter the dataset by materials used in the project through the use of two textboxes and returns the project names into the listbox. So far I have it to where it loads and my listbox populates with the list of projects properly, but the textboxes are not filtering.
Any suggestions on how to fix it would be greatly appreciated.
The code I have so far is:
Imports System.Windows.Data
Imports System.Windows
Public Class SearchMe
Private mds As New MaterialsDataSet
Private pta As New MaterialsDataSetTableAdapters.ProjectTableAdapter
Private mta As New MaterialsDataSetTableAdapters.MaterialsTableAdapter
Private tam As New MaterialsDataSetTableAdapters.TableAdapterManager
Private view As CollectionView
Private Sub SearchMe_Loaded(sender As Object, e As System.Windows.RoutedEventArgs) Handles Me.Loaded
Me.tam.ProjectTableAdapter = pta
Me.tam.MaterialsTableAdapter = mta
Me.pta.Fill(Me.mds.Project)
Me.mta.Fill(Me.mds.Materials)
Me.DataContext = Me.mds.Project
Me.view = CollectionViewSource.GetDefaultView(Me.mds.Project)
End Sub
Private Sub btnSearch_Click(sender As Object, e As System.Windows.RoutedEventArgs) Handles btnSearch.Click
If Material2.Text.Length > 0 Then
Dim query = From p In mds.Project
Join m In mds.Materials On p.ProjectID Equals m.ProjectID
Where m.Material = Me.Material2.Text.ToString
Select p
Else
Dim query = From p In mds.Project
Join m In mds.Materials On p.ProjectID Equals m.ProjectID
Where m.Material = Me.Material1.Text
Select p.ProjectName
Me.DataContext = query
End If
End Sub
Private Sub btnReset_Click(sender As Object, e As System.Windows.RoutedEventArgs) Handles btnReset.Click
Me.DataContext = Nothing
End Sub
Private Sub Material1_TextChanged(sender As Object, e As System.Windows.Controls.TextChangedEventArgs) Handles Material1.TextChanged
End Sub
Private Sub Material2_TextChanged(sender As Object, e As System.Windows.Controls.TextChangedEventArgs) Handles Material2.TextChanged
End Sub
End Class
And the XAML:
<Window x:Class="SearchMe"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="SearchMe" Height="500" Width="750" WindowStartupLocation="CenterScreen" ShowInTaskbar="False" ShowActivated="False" ResizeMode="NoResize">
<Grid>
<ListBox HorizontalAlignment="Right" Margin="0,45,46,60" Name="MyLists" Width="346" BorderThickness="3" BorderBrush="#FF860909"
IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding}"
DisplayMemberPath="ProjectName"/>
<Button Content="Search" Height="23" HorizontalAlignment="Left" Margin="403,417,0,0" Name="btnSearch" VerticalAlignment="Top" Width="75" />
<Button Content="Reset" Height="23" HorizontalAlignment="Left" Margin="556,417,0,0" Name="btnReset" VerticalAlignment="Top" Width="75" />
<TextBox Height="30" HorizontalAlignment="Left" Margin="29,87,0,0" Name="Material1" VerticalAlignment="Top" Width="269" />
<TextBox Height="30" HorizontalAlignment="Left" Margin="29,192,0,0" Name="Material2" VerticalAlignment="Top" Width="269" />
</Grid>
Any and all input appreciated.
There could be many potential problems here, and I haven't had the time to go through your code in detail. But you could try to call the Refresh method on "Me.view" after replacing the DataContext in the click event.
Ok this worked for me... Under the btn_Search Click event:
Dim query = From p In mds.Project
Join m In mds.Materials On p.ProjectID Equals m.ProjectID
Where m.Materia.ToLower().Contain(m.Material1.Text())
Select new with {.ProjectName = p.ProjectName}
Hope this helps anyone out.

Resources