|
Hey, Richard.
Appreciate the feedback. Yeah, that was my take on it as well - ADO.NET should be ADO.NET. However, after a few decades of dealing with MS technologies, I never take that as gospel.
When I get some time I'm going to try it again as the performance difference is significant, but I eyeballed the code pretty intensely and am as sure as I ever am about such things that it was the same in both environments. I hope to be wrong about that because otherwise I'm out of ideas.
Do you use TVPs in your ADO.NET apps?
|
|
|
|
|
Christopher Duncan wrote: Do you use TVPs in your ADO.NET apps?
Yes, although I tend to use the IEnumerable<SqlDataRecord> approach, rather than a DataTable .
private static IEnumerable<SqlDataRecord> AsTableValuedParameter(IEnumerable<string> value)
{
var record = new SqlDataRecord(new SqlMetaData("Value", SqlDbType.NVarChar, 0x100));
foreach (string item in value)
{
record.SetValue(0, item);
yield return record;
}
}
...
IEnumerable<string> roleNames = ...;
var parameter = command.Parameters.AddWithValue("@RoleNames", AsTableValuedParameter(roleNames));
parameter.SqlDbType = SqlDbType.Structured;
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
That's a nice approach. The DataTable was from an example I found on TVPs. I was focused on making the db interaction worked and never thought to convert it to something more elegant. Deadlines and all that.
I'm going to take another swing at this today. Hopefully I just fat fingered something when I cloned the MVC code I was using. Appreciate all the help.
|
|
|
|
|
Well, apparently the fingers are indeed fat. Tried again this morning and it worked without a fuss.
Still using DataTable approach at this point. MS says SqlDataRecord is resource abusive and recommends not creating a new one but reusing a single instance. That aside, are there any benefits to the enumerable approach over populating a data table?
|
|
|
|
|
Christopher Duncan wrote: MS says SqlDataRecord is resource abusive and recommends not creating a new one but reusing a single instance. Which is why I was doing that in the sample I posted.
Christopher Duncan wrote: are there any benefits to the enumerable approach over populating a data table? Not that I'm aware of.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
My bad. Looked like you were allocating a new SqlDataRecord each time but I'm in the US and thus still trying to get my eyes to focus this morning. Need. More. Coffee.
|
|
|
|
|
I have a grid with two expanders in it. See this and this
When I resize the window and make it smaller, the tree's scrollbar does not come on. See this
When I set the Row Definitions to
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
I get this.
When I resize the window smaller the tree resizes correctly so the scrollbar now shows. Here
The problem is that now the expanders are separated instead of stacked.
Here is the XAML - It's a lot, so bear with me I'm desperate!!
<Grid Grid.Row="2"
Grid.Column="0"
Margin="3"
MinWidth="225"
Visibility="{Binding Path=IsUserLoggedIn, Converter={StaticResource BoolToVisConverter}}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!SEARCH>
<Grid Grid.Row="0"
Grid.Column="0"
Background="{StaticResource brushWatermarkBackground}"
Style="{StaticResource searchFieldStyle}"
Margin="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0"
Margin="5,2"
Text="Click here to search "
Foreground="{StaticResource brushWatermarkForeground}"
FontStyle="Italic"
FontSize="14">
<TextBlock.Visibility>
<MultiBinding Converter="{StaticResource TextInputToVisibilityConverter}">
<Binding ElementName="txtUserEntry2"
Path="Text.IsEmpty" />
<Binding ElementName="txtUserEntry2"
Path="IsFocused" />
</MultiBinding>
</TextBlock.Visibility>
</TextBlock>
<TextBox Grid.Column="0"
Name="txtUserEntry2"
Background="Transparent"
Text="{Binding SearchValue}"
FontSize="14"
HorizontalAlignment="Stretch">
<TextBox.InputBindings>
<KeyBinding Key="Enter" Command="{Binding PeformSearchCommand}"/>
<KeyBinding Key="Tab" Command="{Binding PeformSearchCommand}"/>
</TextBox.InputBindings>
</TextBox>
<Button Grid.Column="1"
Height="22"
Width="22"
Margin="2"
ToolTip="Clear Search"
Command="{Binding ClearSearchCommand}">
<Image Source="/Jayhawk.UI.WPF;component/Media/Images/clear.png"/>
</Button>
</Grid>
<!PROJECTS>
<Expander Grid.Row="1"
Header="Projects"
Margin="0,0,0,2"
ScrollViewer.VerticalScrollBarVisibility="Visible"
IsExpanded="{Binding AreProjectsExpanded, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<Grid VerticalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!FILTERS>
<ComboBox Grid.Row="0"
ItemsSource="{Binding ProjectFilters}"
SelectedItem="{Binding SelectedProjectFilter}">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding IsSelected}"
Margin="5" />
<TextBlock Text="{Binding Caption}"
Margin="5" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<!SORT OPTIONS>
<ComboBox Grid.Row="1"
ItemsSource="{Binding ProjectSortOptions}"
SelectedItem="{Binding SelectedProjectSortOption}">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Caption}"
Margin="5" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<!PROJECT LIST>
<TreeView Grid.Row="2"
ItemsSource="{Binding Projects}"
ScrollViewer.VerticalScrollBarVisibility="Visible">
<TreeView.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<Setter Property="IsExpanded" Value="{Binding Expanded, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</Style>
</TreeView.ItemContainerStyle>
</TreeView>
<!PROGRESS INDICATOR>
<Grid Grid.Row="2"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Visibility="{Binding ProjectProgressVisible}">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<progress:SpinningProgress Grid.Row="0"
Height="54"
Width="65"
Margin="5"/>
<TextBlock Grid.Row="1"
Text="Loading..."
HorizontalAlignment="Center"
Margin="2"
Foreground="SteelBlue"
FontSize="18"/>
</Grid>
</Grid>
</Expander>
<!COMPANIES>
<Expander Grid.Row="2"
Header="Companies"
Margin="0,0,0,2"
ScrollViewer.VerticalScrollBarVisibility="Visible"
IsExpanded="{Binding AreCompaniesExpanded}">
<Grid VerticalAlignment="Top">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<ComboBox ItemsSource="{Binding CompanyFilters}">
<ComboBox.ItemTemplate>
<DataTemplate>
<mctrls:MaroisRadioButton IsChecked="{Binding IsSelected, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Content="{Binding Caption}"
GroupName="companyFilters"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<Button Grid.Column="1"
Height="22"
Width="22"
Margin="2"
ToolTip="Reresh Companies"
Command="{Binding RefreshCompaniesCommand}">
<Image Source="/Jayhawk.UI.WPF;component/Media/Images/refresh.png"/>
</Button>
</Grid>
<mctrls:MaroisTreeView Grid.Row="1"
ItemsSource="{Binding Companies}"
SelectedItemEx="{Binding SelectedCompany}"
BorderThickness="0"
BorderBrush="Transparent"
ScrollViewer.VerticalScrollBarVisibility="Auto"
Margin="1"/>
<StackPanel Orientation="Vertical"
Grid.Row="1"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Visibility="{Binding CompanyProgressVisible}">
<progress:SpinningProgress Height="54"
Width="65"
Margin="5"/>
<TextBlock Text="Loading..."
HorizontalAlignment="Center"
Margin="2"
Foreground="SteelBlue"
FontSize="18"/>
</StackPanel>
</Grid>
</Expander>
</Grid>
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
Most of the time, you want "Auto", not "*".
When you use "*", it is typically for the most dynamic / expandable row and / or column; or it is used to take up extra slack "in the container".
When you use more than one "*"; you are asking for rows / columns of proportionally the same size.
If the container is 100, and your "Auto" is 10, then if you have two "*"; you will get "2 of 45".
Also, starting a window "maximized", can affect the proper working of scrollbars; starting it resizable first can help.
And "center" alignment versus stretch will also play a part; while stack panels typically don't "stretch".
And grids-within-grids requires careful planning because one "wrong" Auto or "*", will throw everything "off".
"(I) am amazed to see myself here rather than there ... now rather than then".
― Blaise Pascal
modified 2-Mar-18 16:13pm.
|
|
|
|
|
Hello.
I am writing code Highlight Searched Text with ListView in WPF.
The problem is that when I search a specific word, only match words in the screen visible are hightlighted but the other words in
listviewItems that should be highlighted which are located in the bottom of the listview are not highlighted.
After I run the program and I scroll down manually to the bottom in the list view and when I search the word, then it works well.
What I have tried:
To solve the problem, I added the code like below. Listview scrolls down and up properly like I intented to but the listItems does not highlight still.
// scroll to bottom for the list to make sure every item is in the view
if (listview.Items.Count > 1) listview.ScrollIntoView(listview.Items[listview.Items.Count - 1]);
// scroll back to top to make sure everything looks correct
if (listview.Items.Count > 1) listview.ScrollIntoView(listview.Items[0]);
|
|
|
|
|
|
You're making assumptions based on things you cannot "see".
It's not even confirmed that you are actually "selecting words" at the "bottom"; since you cannot "see" them.
And I've never heard "selected words" used in the context of a listview.
(Is "MultiSelect" on?)
"(I) am amazed to see myself here rather than there ... now rather than then".
― Blaise Pascal
|
|
|
|
|
We have some code which receives images of a document from a C++ DLL, and displays them in a WPF application. The C# code stores the images in an array, which it flushes each time a new document is placed on the scanner. The code converts the image from a Bitmap to a BitmapImage, which is the image type for display in WPF:
private BitmapImage CreateBitmapImage(Bitmap bitmap)
{
using (MemoryStream memory = new MemoryStream())
{
bitmap.Save(memory, ImageFormat.Bmp);
memory.Position = 0;
BitmapImage bitmapimage = new BitmapImage();
bitmapimage.BeginInit();
bitmapimage.StreamSource = memory;
bitmapimage.CacheOption = BitmapCacheOption.OnLoad;
bitmapimage.EndInit();
bitmapimage.Freeze();
return bitmapimage;
}
}
The above code leaks, but only on some PCs. On most it is okay. It can be fine on one Windows 10 PC, and leak on another that has Windows 10 on the same hardware.
A key point to note is that the DLL module is also passing the bitmap handle to a third party validation DLL, and if we remove that DLL, the memory leak disappears.
If I remove the Freeze() call, the code does not leak, but the images are not displayed.
If I comment out the return call, and return null instead, the code still leaks. Therefore the issue is not that we do not clear the stored images.
That this only occurs on some PCs, might suggest a timing issue associated with the validation DLL.
Thoughts?
Note: Edited to correct the code. For some reason I'd copied it with a key line missing!
modified 22-Feb-18 11:29am.
|
|
|
|
|
Are all machines running exactly the same version of .Net?
".45 ACP - because shooting twice is just silly" - JSOP, 2010 ----- You can never have too much ammo - unless you're swimming, or on fire. - JSOP, 2010 ----- When you pry the gun from my cold dead hands, be careful - the barrel will be very hot. - JSOP, 2013
|
|
|
|
|
|
As previously suggested, check the .NET versions on the machines; there have been a few issues that vary by version.
I would probably try moving the creation of the BitmapImage outside of the using block, or try some garbage collection routines, or object disposal to see what kind of response you get from what methods
Director of Transmogrification Services
Shinobi of Query Language
Master of Yoda Conditional
|
|
|
|
|
Oh, I was hoping .Net would be solid. How on earth do we ensure that customers have a bug free version, if that is the cause?
|
|
|
|
|
First you must ensure that your code in itself is bug free.
Director of Transmogrification Services
Shinobi of Query Language
Master of Yoda Conditional
|
|
|
|
|
MadMyche wrote: First you must ensure that your code in itself is bug free.
If I simply discard the BitmapImage created by the quoted code, rather than saving it, the memory leak is present.
|
|
|
|
|
You're trying to create an image from an "empty" memory stream; key statement missing:
bitmap.Save( memory, System.Drawing.Imaging.ImageFormat.Bmp );
"(I) am amazed to see myself here rather than there ... now rather than then".
― Blaise Pascal
|
|
|
|
|
Thanks for spotting that, it actually isn't missing in our code, but it is missing from the sample I pasted here. Ooops. Sorry about that.
|
|
|
|
|
Then maybe you're also running "different" versions of the app ...
(I like to put the version # in the title bar).
"(I) am amazed to see myself here rather than there ... now rather than then".
― Blaise Pascal
|
|
|
|
|
No, just stupidity on my part when copying code to this forum.
|
|
|
|
|
Thank you to everyone for your thoughts. It appears to be unrelated to the version of .Net.
I found the source for MemoryStream and the Dispose method does NOT set the buffer reference to null. I tried assigning a static buffer to the MemoryStream instance instead of allowing it to allocate its own buffer but that caused a crash.
I created test WPF and WinForms apps and the results are bizarre.
We have a small C# class - VideoOCRWrapper - which drives an attached OCR document scanner. It essentially makes calls to a C++ DLL, and has a callback which receives a IntPtr containing a HWND. On receipt of a bitmap, it converts it to a BitmapImage and fires an event to provide a client with the BitmapImage isntance.
I created a WinForms app, which initialises VideoOCRWrapper and displays the received bitmap. It has converts the BitmapImage to a Bitmap for display.It shows no memory leaks.
I created a WPF app, which initialises VideoOCRWrapper and displays the received bitmap. It shows a huge memory leak consistent with the bitmap buffer leaking.
The two apps use almost the same code, except that the WinForms overrides the form's WndProc, whereas the WPF app hooks its own WndProc onto the main window.
I memory profiled the WPF test app, and it said that "22 types have instances that are queued for finalization. This can indicate that a Finalizer method is stuck, which will prevent instances from being finalized and cause memory leaks.".
There is an extra factor. We use a third party DLL for document verification, which receives bitmaps from us. If I remove that DLL, our code shows no leaks. If I add that DLL, we have leaks but only when running our WPF test app, or our WPF application. When running the WinForms test app, we have no leaks.
|
|
|
|
|
I am working on a WPF application handling lists too long to fit in the window, so it needs a scroll bar. But elements of the list (a vertical stack panel) may flash up indicators that preferably should be acted on without too much delay; they should not be outside the window.
So I imagine a modified scrollbar mechanisms: A certain fraction of the contents is displayed in normal size (or even normal++, for those of us who are not as young as we used to be). Lines above or below this area is gradually reduced in size, so that more of them would fit above/below the "reading zone" of the window (with the attention indicators visible), without scrolling out. The reading zone would be somewhat like a cylinder lens, except with a central flat area of constant magnification.
Preferably, the size falloff outside the reading zone should be configurable, as well as the fraction of the window making up the reading zone. It would also be nice if it could be applied to columns of a table one-by-one, so that the columns remain straight from top to bottom, even though the cell contents is reduced in size.
I tried to google for 'cylinder lens scrollbar', without much success. Has anyone around here seen such a scrolling mechanism? Do you have hits for other google terms? Or should I just sit down and start implementing it myself?
(I suspect that my implmentation would be too much tailored to my specific needs at the moment; if there is anything like this out in the wild, it is probably of far more general use!)
|
|
|
|
|
You want "dynamic" font sizes relatived to the position of an item in the "view port".
Nothing really to do with "scroll bars" per se.
You need "code behind" to assign "font sizes" to each item (e.g. user control) in your observable collection based on your view port and item position.
Or, create a fixed set of "panes", of different font size; and "pass" items through them. Simulates a list and probably easier to grok.
(Or use a vertical "carousel" control).
WPF: Carousel Control
CodePlex Archive
"(I) am amazed to see myself here rather than there ... now rather than then".
― Blaise Pascal
modified 19-Feb-18 13:03pm.
|
|
|
|
|