Render Canvas with Background to Bitmap fails to display background C#/WPF - c#

I am writing an app in C#4.0/WPF that displays a piece of machinery in an image control within a canvas. The user drags coloured text blocks on to the image to indicate an area of wear or damage (I have written code that creates and moves a new text block as a user drags it). Once the user has completed dragging the text blocks on the canvas my aim is to capture background and text blocks in a bitmap to be sent to a report. The trouble is that when I try and do this the image that is captured shows only the text blocks that have been dragged and not the background. I have created a test project with what looks like exactly the same code to me and it captures the canvas with all contents perfectly. I have not included the code that performs the text block dragging in the test project as I dont think it is relevant, however I have included it here for clarity. I have included the relevant code from both the main and test app. I have also included images produced in both the main and test apps. I am not too hot on XAML so I suspect this is where the fault lies. I have tried to post images from both test and main apps but the site will not allow as I have less than 10 rep points! I can of course do this once I have the points.I have not included all XAML for the form as it is a big form and there is a lot of code - I can do this if required though.I have researched high and low and have posted this on other forums with no luck. Hope some one can help!
Many Thanks, Jeff
and apologies for the long posting!
Test App XAML:
<Canvas Name="canvBlade1Image" Margin="33,23,719,6">
<TextBlock Height="15" Name="tblkRed" Width="18" FontSize="11" Background="Red" Canvas.Left="200" Canvas.Top="444" HorizontalAlignment="Center" TextAlignment="Center" />
<TextBlock Background="Orange" FontSize="11" Height="15" Name="tblkOrange" TextAlignment="Center" Width="18" Canvas.Left="200" Canvas.Top="465" />
<TextBlock Background="Yellow" FontSize="11" Height="15" Name="tblkYellow" TextAlignment="Center" Width="18" Canvas.Left="200" Canvas.Top="486" />
<TextBlock Background="Lime" FontSize="11" Height="15" Name="tblkGreen" TextAlignment="Center" Width="18" Canvas.Left="200" Canvas.Top="508" />
<TextBlock Background="DodgerBlue" FontSize="11" Height="15" Name="tblkGre" TextAlignment="Center" Width="18" Canvas.Left="200" Canvas.Top="528" />
<Canvas.Background>
<ImageBrush ImageSource="C:\Users\jeff\documents\blankblade.png" Stretch="Fill"></ImageBrush>
</Canvas.Background>
test app C#
private void btnRendertoBitmap_Click(object sender, RoutedEventArgs e)
{
Transform transform = canvBlade1Image.LayoutTransform;
canvBlade1Image.LayoutTransform = null;
Size size = new Size(canvBlade1Image.ActualWidth, canvBlade1Image.ActualHeight);
canvBlade1Image.Measure(size);
canvBlade1Image.Arrange(new Rect(size));
RenderTargetBitmap renderBitmap = new RenderTargetBitmap((int)size.Width, (int)size.Height, 96d, 96d, PixelFormats.Pbgra32);
renderBitmap.Render(canvBlade1Image);
using (FileStream outStream = new FileStream(#"C:\Users\jeff\documents\blade.png.", FileMode.Create))
{
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(renderBitmap));
encoder.Save(outStream);
}
}
![test app output][1]
Main app XAML
<Canvas Name="canvBlade1Image" Margin="33,23,719,6">
<TextBlock Height="15" Name="tblkRed" Width="18" FontSize="11" Background="Red" Canvas.Left="200" Canvas.Top="444" HorizontalAlignment="Center" TextAlignment="Center" />
<TextBlock Background="Orange" FontSize="11" Height="15" Name="tblkOrange" TextAlignment="Center" Width="18" Canvas.Left="200" Canvas.Top="465" />
<TextBlock Background="Yellow" FontSize="11" Height="15" Name="tblkYellow" TextAlignment="Center" Width="18" Canvas.Left="200" Canvas.Top="486" />
<TextBlock Background="Lime" FontSize="11" Height="15" Name="tblkGreen" TextAlignment="Center" Width="18" Canvas.Left="200" Canvas.Top="508" />
<TextBlock Background="DodgerBlue" FontSize="11" Height="15" Name="tblkGre" TextAlignment="Center" Width="18" Canvas.Left="200" Canvas.Top="528" />
<Canvas.Background>
<ImageBrush ImageSource="C:\Users\jeff\documents\blankblade.png" Stretch="Fill"></ImageBrush>
</Canvas.Background>
Main App C#
public bool ExportToPNG()
{
try
{
Transform transform = canvBlade1Image.LayoutTransform;
canvBlade1Image.LayoutTransform = null;
Size size = new Size(canvBlade1Image.ActualWidth, canvBlade1Image.ActualHeight);
canvBlade1Image.Measure(size);
canvBlade1Image.Arrange(new Rect(size));
RenderTargetBitmap renderBitmap = new RenderTargetBitmap((int)size.Width, (int)size.Height, 96d, 96d, PixelFormats.Pbgra32);
renderBitmap.Render(canvBlade1Image);
using (FileStream outStream = new FileStream(#"C:\Users\jeff\documents\blade.png.", FileMode.Create))
{
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(renderBitmap));
encoder.Save(outStream);
}
return true;
}
catch (Exception E)
{
MessageBox.Show("Error converting blade image" + E);
return false;
}
}
![Main app output][2]
Code to drag textblocks
private void canvBlade1Image_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if(doNotAllowNewFault == true && (((System.Windows.Controls.TextBlock)(e.Source)).Text == ""))
{
return;
}
if (e.Source != canvBlade1Image && e.Source.GetType() == typeof(System.Windows.Controls.TextBlock))
{
overlayTextBlockBackgroundBrush = ((System.Windows.Controls.TextBlock)(e.Source)).Background;
overlayTextBlockTextAlignment = TextAlignment.Center;
overlayTextBlockFontSize = ((System.Windows.Controls.TextBlock)(e.Source)).FontSize;
overlayTextBlockText = ((System.Windows.Controls.TextBlock)(e.Source)).Text;
canvBlade1Image.Children.Remove(sourceTextBlock);
if(((System.Windows.Controls.TextBlock)(e.Source)).Text !="")
{
moveFault = true;
}
sourceElementLeft = Canvas.GetLeft((TextBlock)e.Source);
sourceElementTop = Canvas.GetLeft((TextBlock)e.Source);
canvBlade1Image.Children.Remove(sourceTextBlock);
sourceTextBlock = (TextBlock)e.Source;
mIsDown = true;
mStartPoint = e.GetPosition(canvBlade1Image);
e.Handled = true;
}
}
private void canvBlade1Image_MouseMove(object sender, MouseEventArgs e)
{
Double actualX = Math.Abs(e.GetPosition(canvBlade1Image).X);
Double startX = mStartPoint.X;
Double actualY = Math.Abs(e.GetPosition(canvBlade1Image).Y);
Double startY = mStartPoint.Y;
if (mIsDown)
{
if (!mIsDragging)
{
DragStarted();
}
}
if (mIsDragging)
{
DragMoved();
}
e.Handled = true;
}
private void DragStarted()
{
mIsDragging = true;
sourceElementLeft = Canvas.GetLeft(sourceTextBlock);
sourceElementTop = Canvas.GetTop(sourceTextBlock);
overlayTextBlock = new TextBlock();
overlayTextBlock.Background = sourceTextBlock.Background;
overlayTextBlock.Width = sourceTextBlock.RenderSize.Width;
overlayTextBlock.Height = sourceTextBlock.RenderSize.Height;
if (moveFault == false)
{
overlayTextBlock.Text = blade1FaultNumber.ToString();
}
else
{
overlayTextBlock.Text =overlayTextBlockText;
}
overlayTextBlock.FontSize = overlayTextBlockFontSize;
overlayTextBlock.TextAlignment = overlayTextBlockTextAlignment;
canvBlade1Image.Children.Add(overlayTextBlock);
overlayTextBlock.Opacity = 1;
}
private void DragMoved()
{
Point currentPosition = Mouse.GetPosition(canvBlade1Image);
double elementLeft = (currentPosition.X - mStartPoint.X) + sourceElementLeft;
double elementTop = (currentPosition.Y - mStartPoint.Y) + sourceElementTop;
Canvas.SetLeft(overlayTextBlock, elementLeft);
Canvas.SetTop(overlayTextBlock, elementTop);
}
private void canvBlade1Image_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (mIsDown)
{
DragFinished(false);
e.Handled = true;
}
}
private void DragFinished(Boolean cancelled)
{
if (mIsDragging)
{
if( moveFault)
{
canvBlade1Image.Children.Remove(sourceTextBlock);
}
else
{
Canvas.SetLeft(sourceTextBlock, Canvas.GetLeft(overlayTextBlock));
Canvas.SetTop(sourceTextBlock, Canvas.GetTop(overlayTextBlock));
TextBlock replacementTextBlock = new TextBlock();
Canvas.SetLeft(replacementTextBlock, sourceElementLeft);
Canvas.SetTop(replacementTextBlock, sourceElementTop);
replacementTextBlock.Height = overlayTextBlock.Height;
replacementTextBlock.Width = overlayTextBlock.Width;
replacementTextBlock.Opacity = 1;
replacementTextBlock.FontSize = 11;
replacementTextBlock.Background = overlayTextBlock.Background;
blade1FaultNumber++;
canvBlade1Image.Children.Add(replacementTextBlock);
}
moveFault = false;
overlayTextBlock = null;
mIsDragging = false;
mIsDown = false;
txtFaultBriefDesciption1.IsEnabled = true;
txtFaultdetails1.IsEnabled = true;
cboMeters1.IsEnabled = true;
}
}

How about you add this to your canvas and get rid of the background?:
Canvas Name="canvBlade1Image" Margin="33,23,719,6">
...other stuff on canvas
Image Source="C:\Users\jeff\documents\blankblade.png"/>
/Canvas>

After much frustration I have now been able to resolve this issue. I was unable to find out why the background was not rendering in my prod app with exactly the same code as my successful test app. I therefore tried a new route of explicitly rendering the background. This worked, code below:
try
{
RenderTargetBitmap renderBitmap = new RenderTargetBitmap(
(int)canvBlade1Image.ActualWidth,(int)canvBlade1Image.ActualHeight,96d,
96d, PixelFormats.Pbgra32);
DrawingVisual drawingVisual = new DrawingVisual();
using (DrawingContext drawingContext = drawingVisual.RenderOpen())
drawingContext.DrawRectangle(canvBlade1Image.Background, null, new Rect(0, 0, canvBlade1Image.ActualWidth, canvBlade1Image.ActualHeight));
renderBitmap.Render(drawingVisual);
renderBitmap.Render(canvBlade1Image);
using (FileStream outStream = new FileStream(#"C:\Images\Keep\img1.png.", FileMode.Create))
{
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(renderBitmap));
encoder.Save(outStream);
}
}

Related

Control not visible even visibility set to visible

I am creating a window, in which click on save communicate with database and save data in database. I want to show progress image on click on save until data is not saved in database. I have set the visibility of image to true but still that progress image is not visible.
I have done following code...
In xml file..
<TextBox x:Name="txt_Comment" VerticalScrollBarVisibility="Auto" TextWrapping="Wrap" AcceptsReturn="True" MaxLength="5000" Margin="2,2,2,0"></TextBox>
<WrapPanel Grid.Row="1" HorizontalAlignment="Center" Margin="10,-15,0,0" VerticalAlignment="Center">
<Button x:Name="btn_Ok" Margin="0,0,0,0" HorizontalAlignment="Center" VerticalAlignment="Center" Click="btn_Save_Click" Height="25" Width="55">Save</Button>
<Button x:Name="btn_Cancel" Margin="10,0,0,0" HorizontalAlignment="Center" VerticalAlignment="Center" Height="25" Width="55" Content="Cancel" Click="btn_Cancel_Click" >
</Button>
</WrapPanel>
<Grid Grid.RowSpan="2" Background="Black" Opacity="0.25" Name="LoadingAdorner" Visibility="Hidden"/>
<Border Width="400" Grid.RowSpan="2" Opacity="1" Height="180" Visibility="Hidden" HorizontalAlignment="Center" VerticalAlignment="Center" CornerRadius="2" x:Name="loaderBorder">
<Border.Background>
<LinearGradientBrush EndPoint="1,1" StartPoint="0,0" >
<GradientStop Color="#EBF6FA" Offset="0.3"/>
<GradientStop Color="#b7d9e5" Offset="1.0"/>
</LinearGradientBrush>
</Border.Background>
<Border.Effect>
<DropShadowEffect BlurRadius="5" Color="#FFB0B0B0" ShadowDepth="3" />
</Border.Effect>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition/>
<RowDefinition Height="95"/>
</Grid.RowDefinitions>
<Controls:LoadingAnimation Grid.Row="1" HorizontalAlignment="Center" FontWeight="Bold" LoadingText="Loading..." VerticalAlignment="Center" />
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" FontWeight="Bold" FontFamily="Arial" Foreground="#647883" FontSize="14" Grid.Row="2" Text="Saving..."></TextBlock>
</Grid>
</Border>
</Grid>
In code behind page..
BackgroundWorker worker = new BackgroundWorker { WorkerSupportsCancellation = true };
worker.DoWork += delegate(object sender1, DoWorkEventArgs e1)
{
CurrentDispatcher.Invoke(
new Action(() =>
{
if (!string.IsNullOrEmpty(txt_Comment.Text))
{
LoadingAdorner.Visibility = Visibility.Visible;
loaderBorder.Visibility = Visibility.Visible;
using (Entities DB = new Entities(settings.LinqConnection))
{
if (txt_Comment.Text.Length > 1000)
{//In this case loading image is visible
MessageBox.Show("Comment is too large.", "Alert !", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
var comment = DB.Table1.Create();//Here loading image is not visible.
comment.value = txt_Comment.Text;
comment.Date = DateTime.Now;
comment.ModifiedBy = settings.CurrentUID;
DB.Table1.Add(comment);
DB.SaveChanges();
}
}
}),
DispatcherPriority.Normal);
};
worker.RunWorkerCompleted += delegate(object s, RunWorkerCompletedEventArgs args)
{
this.DialogResult = true;
this.Close();
LoadingAdorner.Visibility = Visibility.Collapsed;
loaderBorder.Visibility = Visibility.Collapsed;
};
worker.RunWorkerAsync();
When messagebox is visible than loading image is visible, but when data is saving in database then loading image is not visible.
This is how i would have done in such situation :
Create delegate to update your visibility and corresponding method
Wrap your anonymous function in a function compatible with doWork event
Create a new delegate and call the update method using dispatcher.BeginInvoke() when you need to update visibility.
private delegate void UpdateVisibilityDelegate(Visibility visibility);
private void UpdateVisiblity(Visibility visibility)
{
//LoadingAdorner.Visibility = visibility;
//loaderBorder.Visibility = visibility;
}
private void Worker_DoWork(object sender, DoWorkEventArgs e)
{
// Your Action() code here
// Change the visibility using this method
Dispatcher.CurrentDispatcher.BeginInvoke(new UpdateVisibilityDelegate(this.UpdateVisiblity), Visibility.Visible);
}
Move your using block out of CurrentDispatcher.Invoke() and put after this call.
BackgroundWorker worker = new BackgroundWorker { WorkerSupportsCancellation = true };
worker.DoWork += delegate(object sender1, DoWorkEventArgs e1)
{
CurrentDispatcher.Invoke(
new Action(() =>
{
if (!string.IsNullOrEmpty(txt_Comment.Text))
{
LoadingAdorner.Visibility = Visibility.Visible;
loaderBorder.Visibility = Visibility.Visible;
}
}),
DispatcherPriority.Normal);
using (Entities DB = new Entities(settings.LinqConnection))
{
if (txt_Comment.Text.Length > 1000)
{//In this case loading image is visible
MessageBox.Show("Comment is too large.", "Alert !", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
var comment = DB.Table1.Create();//Here loading image is not visible.
comment.value = txt_Comment.Text;
comment.Date = DateTime.Now;
comment.ModifiedBy = settings.CurrentUID;
DB.Table1.Add(comment);
DB.SaveChanges();
}
};
so this code works for me:
private void Button_Click(object sender, RoutedEventArgs e)
{
var worker = new BackgroundWorker { WorkerSupportsCancellation = true };
worker.DoWork += delegate (object sender1, DoWorkEventArgs e1)
{
Dispatcher.Invoke(
new Action(() =>{testCtl.Visibility = Visibility.Visible;}),
System.Windows.Threading.DispatcherPriority.Normal);
Task.Delay(3000).Wait();
};
worker.RunWorkerCompleted += delegate (object s, RunWorkerCompletedEventArgs args)
{
testCtl.Visibility = Visibility.Collapsed;
};
worker.RunWorkerAsync();
}

Why is my textbox loaded text disappearing

I have a textbox ACLBox that I want to display a string upon initialization of the user interface. Upon initializing, the string flashes for a second then disappears. Why?
Here's the xaml code for the textbox:
<Window x:Class="Funnel.ACL"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Funnel"
mc:Ignorable="d"
Title="ACL Configuration" Height="300" Width="560" WindowStartupLocation="CenterScreen"
Closing="exitACL"
Background="LightGray" Name="ACLConfiguration">
<Grid>
<DockPanel>
<Grid x:Name="FunnelGrid" DockPanel.Dock="Top" ShowGridLines="False">
<!--Defining Grid-->
<Grid.ColumnDefinitions>
<ColumnDefinition Width="130"/>
<ColumnDefinition Width="40"/>
<ColumnDefinition Width="40"/>
<ColumnDefinition Width="40"/>
<ColumnDefinition Width="40"/>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="70"/>
<ColumnDefinition Width="75"/>
<ColumnDefinition Width="75"/>
<ColumnDefinition Width="75"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Label x:Name="Config"
Content="ACL CONFIGURATION"
Grid.Row="0"
Grid.Column="0"
Grid.ColumnSpan="9"
HorizontalAlignment="Center"
Foreground="Blue"
FontWeight="Heavy"
FontSize="16">
</Label>
<CheckBox x:Name="aclCheckbox"
FlowDirection="RightToLeft"
Content="ACL ON"
Foreground="Blue"
FontWeight="Heavy"
FontSize="16"
Grid.Row="1"
Grid.Column="0"
Grid.RowSpan="1"
Grid.ColumnSpan="5"
HorizontalAlignment="Center"
Checked="ACL_Check"
Unchecked="ACL_Unchecked"
/>
<Label x:Name="AddIPAddress" Content="Add IP Address" Grid.Row="2" Grid.Column="0" Width="90" Height="30"></Label>
<TextBox x:Name="AddIPTextBox1" Grid.Row="2" Grid.Column="1" Width="35" Height="20" TextChanged="AddIPTextBox1_TextChanged"></TextBox>
<TextBox x:Name="AddIPTextBox2" Grid.Row="2" Grid.Column="2" Width="35" Height="20" TextChanged="AddIPTextBox2_TextChanged"></TextBox>
<TextBox x:Name="AddIPTextBox3" Grid.Row="2" Grid.Column="3" Width="35" Height="20" TextChanged="AddIPTextBox3_TextChanged"></TextBox>
<TextBox x:Name="AddIPTextBox4" Grid.Row="2" Grid.Column="4" Width="35" Height="20" TextChanged="AddIPTextBox4_TextChanged"></TextBox>
<TextBox x:Name="AddErrorBox" Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" HorizontalAlignment="Right" BorderThickness="0" Background="LightGray" FontSize="10" Text="{Binding AddErrorText}"/>
<Button x:Name="AddButton" Grid.Row="3" Grid.Column="1" Grid.ColumnSpan="4" HorizontalAlignment="Center" Height="25" Width="50" Click="addClick" FontSize="12" FontWeight="ExtraBold" Background="LightSteelBlue" VerticalAlignment="Top">ADD</Button>
<Label x:Name="DelIPAddress" Content="Remove IP Address" Grid.Row="4" Grid.Column="0" Width="120" Height="30"></Label>
<TextBox x:Name="DeleteIPTextBox1" Grid.Row="4" Grid.Column="1" Width="35" Height="20" TextChanged="DeleteIPTextBox1_TextChanged"></TextBox>
<TextBox x:Name="DeleteIPTextBox2" Grid.Row="4" Grid.Column="2" Width="35" Height="20" TextChanged="DeleteIPTextBox2_TextChanged"></TextBox>
<TextBox x:Name="DeleteIPTextBox3" Grid.Row="4" Grid.Column="3" Width="35" Height="20" TextChanged="DeleteIPTextBox3_TextChanged"></TextBox>
<TextBox x:Name="DeleteIPTextBox4" Grid.Row="4" Grid.Column="4" Width="35" Height="20" TextChanged="DeleteIPTextBox4_TextChanged"></TextBox>
<TextBox x:Name="DelErrorBox" Grid.Row="5" Grid.Column="0" Grid.ColumnSpan="2" HorizontalAlignment="Right" BorderThickness="0" Background="LightGray" FontSize="10" Text="{Binding DelErrorText}"/>
<Button x:Name="DeleteButton" Grid.Row="5" Grid.Column="1" Grid.ColumnSpan="4" HorizontalAlignment="Center" Height="25" Width="50" Click="deleteClick" FontSize="12" FontWeight="ExtraBold" Background="LightSteelBlue" VerticalAlignment="Top">DELETE</Button>
<Button x:Name="DeleteAllButton" Grid.Row="6" Grid.Column="1" Grid.ColumnSpan="4" HorizontalAlignment="Center" Height="25" Width="80" Click="deleteAllClick" FontSize="12" FontWeight="ExtraBold" Background="LightSteelBlue" VerticalAlignment="Top">REMOVE ALL</Button>
<Label x:Name="ACLBoxLabel" Content="Access Control List" Foreground="Blue" Grid.Row="1" Grid.Column="6" Grid.ColumnSpan="3" HorizontalAlignment="Center"></Label>
<TextBox x:Name="ACLBox"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollViewer.VerticalScrollBarVisibility="Auto"
ScrollViewer.CanContentScroll="True"
Grid.Row="2"
Grid.Column="6"
Grid.RowSpan="4"
Grid.ColumnSpan="4"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Width="220"
Height="150"
FontSize="14"
IsReadOnly="True"
Text="{Binding ACLBoxText}"
TextWrapping="Wrap"
TextAlignment="Center" />
</Grid>
</DockPanel>
</Grid>
Here's the C# code for the string:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace Funnel
{
/// <summary>
/// Interaction logic for ACL.xaml
/// </summary>
public partial class ACL : Window
{
AclManager _manage = new AclManager();
FileController _controller = new FileController();
string addStr1;
string addStr2;
string addStr3;
string addStr4;
bool addError;
string delStr1;
string delStr2;
string delStr3;
string delStr4;
bool delError;
public string aclText;
public event PropertyChangedEventHandler PropertyChanged;
public ACL()
{
InitializeComponent();
if(FunnelGlobals.accessControlList)
{
aclCheckbox.IsChecked = true;
}
aclText = _manage.getAclList();
}
private void exitACL(object sender,System.ComponentModel.CancelEventArgs e)
{
_controller.writeAclFile();
}
private void ACL_Check(object sender, RoutedEventArgs e)
{
FunnelGlobals.accessControlList = true;
aclText = _manage.getAclList();
}
private void ACL_Unchecked(object sender, RoutedEventArgs e)
{
FunnelGlobals.accessControlList = false;
aclText = _manage.getAclList();
}
private void AddIPTextBox1_TextChanged(object sender, TextChangedEventArgs e)
{
AddErrorBox.Text = "";
AddIPTextBox1.Text = AddIPTextBox1.Text;
addStr1 = AddIPTextBox1.Text;
if(!_manage.isDigit(addStr1))
{
Color foreColor = (Color)new ColorConverter().ConvertFrom("red");
Brush errBrush = new SolidColorBrush(foreColor);
AddErrorBox.Foreground = errBrush;
AddErrorBox.Text = "Character NOT Valid";
addError = true;
}
else
{
addError = false;
}
ACLBox.Text = _manage.getAclList();
}
private void AddIPTextBox2_TextChanged(object sender, TextChangedEventArgs e)
{
AddErrorBox.Text = "";
AddIPTextBox2.Text = AddIPTextBox2.Text;
addStr2 = AddIPTextBox2.Text;
if (!_manage.isDigit(addStr2))
{
Color foreColor = (Color)new ColorConverter().ConvertFrom("red");
Brush errBrush = new SolidColorBrush(foreColor);
AddErrorBox.Foreground = errBrush;
AddErrorBox.Text = "Character NOT Valid";
}
aclText = _manage.getAclList();
}
private void AddIPTextBox3_TextChanged(object sender, TextChangedEventArgs e)
{
AddErrorBox.Text = "";
AddIPTextBox3.Text = AddIPTextBox3.Text;
addStr3 = AddIPTextBox3.Text;
if (!_manage.isDigit(addStr3))
{
Color foreColor = (Color)new ColorConverter().ConvertFrom("red");
Brush errBrush = new SolidColorBrush(foreColor);
AddErrorBox.Foreground = errBrush;
AddErrorBox.Text = "Character NOT Valid";
}
aclText = _manage.getAclList();
}
private void AddIPTextBox4_TextChanged(object sender, TextChangedEventArgs e)
{
AddErrorBox.Text = "";
AddIPTextBox4.Text = AddIPTextBox4.Text;
addStr4 = AddIPTextBox4.Text;
if (!_manage.isDigit(addStr4))
{
Color foreColor = (Color)new ColorConverter().ConvertFrom("red");
Brush errBrush = new SolidColorBrush(foreColor);
AddErrorBox.Foreground = errBrush;
AddErrorBox.Text = "Character NOT Valid";
}
aclText = _manage.getAclList();
}
private void addClick(object sender, RoutedEventArgs e)
{
String addStr = addStr1 + "." + addStr2 + "." + addStr3 + "." + addStr4;
if(_manage.isLegit(addStr))
{
FunnelGlobals.aclIPs.Add(addStr);
}
if(addError)
{
Color foreColor = (Color)new ColorConverter().ConvertFrom("red");
Brush errBrush = new SolidColorBrush(foreColor);
AddErrorBox.Foreground = errBrush;
AddErrorBox.Text = "Fix Invalid Characters before Adding";
}
else
{
aclText = _manage.getAclList();
}
}
private void DeleteIPTextBox1_TextChanged(object sender, TextChangedEventArgs e)
{
DelErrorBox.Text = "";
DeleteIPTextBox1.Text = DeleteIPTextBox1.Text;
delStr1 = DeleteIPTextBox1.Text;
if (!_manage.isDigit(delStr1))
{
Color foreColor = (Color)new ColorConverter().ConvertFrom("red");
Brush errBrush = new SolidColorBrush(foreColor);
DelErrorBox.Foreground = errBrush;
DelErrorBox.Text = "Character NOT Valid";
delError = true;
}
else
{
delError = false;
}
}
private void DeleteIPTextBox2_TextChanged(object sender, TextChangedEventArgs e)
{
DelErrorBox.Text = "";
DeleteIPTextBox2.Text = DeleteIPTextBox2.Text;
delStr2 = DeleteIPTextBox2.Text;
if (!_manage.isDigit(delStr2))
{
Color foreColor = (Color)new ColorConverter().ConvertFrom("red");
Brush errBrush = new SolidColorBrush(foreColor);
DelErrorBox.Foreground = errBrush;
DelErrorBox.Text = "Character NOT Valid";
delError = true;
}
else
{
delError = false;
}
}
private void DeleteIPTextBox3_TextChanged(object sender, TextChangedEventArgs e)
{
DelErrorBox.Text = "";
DeleteIPTextBox3.Text = DeleteIPTextBox3.Text;
delStr3 = DeleteIPTextBox3.Text;
if (!_manage.isDigit(delStr3))
{
Color foreColor = (Color)new ColorConverter().ConvertFrom("red");
Brush errBrush = new SolidColorBrush(foreColor);
DelErrorBox.Foreground = errBrush;
DelErrorBox.Text = "Character NOT Valid";
delError = true;
}
else
{
delError = false;
}
}
private void DeleteIPTextBox4_TextChanged(object sender, TextChangedEventArgs e)
{
DelErrorBox.Text = "";
DeleteIPTextBox4.Text = DeleteIPTextBox4.Text;
delStr4 = DeleteIPTextBox4.Text;
if (!_manage.isDigit(delStr4))
{
Color foreColor = (Color)new ColorConverter().ConvertFrom("red");
Brush errBrush = new SolidColorBrush(foreColor);
DelErrorBox.Foreground = errBrush;
DelErrorBox.Text = "Character NOT Valid";
delError = true;
}
else
{
delError = false;
}
}
private void deleteClick(object sender, RoutedEventArgs e)
{
String delStr = delStr1 + "." + delStr2 + "." + delStr3 + "." + delStr4;
FunnelGlobals.aclIPs.Remove(delStr);
if (delError)
{
Color foreColor = (Color)new ColorConverter().ConvertFrom("red");
Brush errBrush = new SolidColorBrush(foreColor);
DelErrorBox.Foreground = errBrush;
DelErrorBox.Text = "Fix Invalid Characters before Removing";
}
else
{
aclText = _manage.getAclList();
}
}
private void deleteAllClick(object sender, RoutedEventArgs e)
{
FunnelGlobals.aclIPs.Clear();
aclText = _manage.getAclList();
}
private void ACLBox_Loaded(object sender, RoutedEventArgs e)
{
ACLBox.Text = _manage.getAclList();
}
public string ACLBoxText
{
get { return aclText; }
set { aclText = value; OnNotifyPropertyChanged("ACLBoxText"); }
}
private void OnNotifyPropertyChanged(string v)
{
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(v));
throw new NotImplementedException();
}
}
}
Upon initializing, the string flashes for a second then disappears. Why?
Probably because you are "overwriting" the value of the ACLBoxText source property, which is initially displayed in the TextBlock, when you set the Text property of the TextBlock in your Loaded event handler.
If the TextBlock is empty once the UI has been loaded you should make sure that the _manage.getAclList() method returns the string that you expect it to return. You could temporarily try to assign the Text property to a "static" value:
private void ACLBox_Loaded(object sender, RoutedEventArgs e)
{
ACLBox.Text = "TEXT";
}
But I agree that it doesn't make much sense to first bind the Text property of the TextBlock to a source property in the XAML markup and then handle the Loaded event of the same TextBlock and set its Text property to a new value in this event handler. But I guess you have your reasons...
Note that binding that you define in the XAML markup will get reset when you programmatically set the Text property in your Loaded handler though.
So you should either don't bind the Text property in the XAML markup, or don't handle the Loaded event and set the Text property programmatically. It's one or the other but not both.
I figured out the problem. This is my first C# project and first time ever using Xaml (wpf) so I misunderstood binding. I bound the text like I did in the primary gui. The text is never getting triggered within this gui so I could only see the text flash because of loaded but then the text binding reset the textbox to nothing. When I changed my text to not be bound then everything works as I wanted. Lesson learned. Binding is only needed when accessing a textbox from within .cs files. It is not needed within xaml.cs. Since my text would only ever be triggered by xaml.cs just setting text the usual way(ie textbox.text = "whatever") does what I need. Thank you everyone for your help. I understand binding much, much better now. Java does things differently. :)
As Ed Plunkett has already mentioned, you should use your ACLBoxText backing variable instead of resetting the control value.
Something like this will work:
private void ACLBox_Loaded(object sender, RoutedEventArgs e)
{
ACLBoxText = _manage.getAclList();
}
Unfortunately, the view doesn't know about changes to backing properties unless you tell it that something changed. You need to implement INotifyPropertyChanged:
private string _aclBoxText;
public string ACLBoxText {
get { return _aclBoxText; }
set {
_aclBoxText = value;
OnNotifyPropertyChanged("ACLBoxText");
}
}
protected void OnNotifyPropertyChanged(string name)
{
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(name));
}
public event PropertyChangedEventHandler PropertyChanged;

How to update ObservableCollection?

I have folder with images, which I show in my ListBox. ObservableCollection stores that images. In my program users could crop selected image and after cropping save that image. Problem is that after saving the image my ObservableCollection is not updated (although OnPropertyChange event is rise) and shows the same image. Does anybody have the same problem?
EDIT
I have BindingManager where I place my observableCollection.
public class BindingsManager:INotifyPropertyChanged
{
private ObservableCollection<PhotoModel> _photoList;
public ObservableCollection<PhotoModel> PhotoList
{
get {return _photoList;}
set
{
_photoList = value;
OnPropertyChanged(nameof(PhotoList));
}
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
In Xaml file I bind source to PhotoList:
<ListView x:Name="PhotoListView" ItemsSource="{Binding PhotoList, UpdateSourceTrigger=PropertyChanged}">
After double click on image, image will be opened in new window where user can crop it and save to DefaultDestFolder which is tracking by FileSystemWatcher:
private void WatchDestinationFolder()
{
var watcher = new FileSystemWatcher
{
Path = BindingsManager.DefaultsManager.DefaultDestFolder,
NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.Size | NotifyFilters.LastAccess | NotifyFilters.LastWrite,
Filter = "*.*"
};
watcher.Changed += UpdatePhotoList;
watcher.EnableRaisingEvents = true;
}
And on change event i update my ObservableCollection but it doesn't work:
private void UpdatePhotoList()
{
var files = Directory.GetFiles(BindingsManager.DefaultsManager.DefaultDestFolder, "*.*");
BindingsManager.PhotoList = new ObservableCollection<PhotoModel>();
foreach (var file in files)
{
Application.Current.Dispatcher.Invoke((Action)(() =>
{
var fileInfo = new FileInfo(file);
BitmapImage img = new BitmapImage();
img.BeginInit();
img.CacheOption = BitmapCacheOption.OnLoad;
img.UriSource = new Uri(file, UriKind.Absolute);
img.EndInit();
BindingsManager.PhotoList.Add(new PhotoModel()
{
BitmapImage = img,
FullFileName = fileInfo.FullName,
ShortFileName = fileInfo.Name,
FileLastAccessTime = fileInfo.LastAccessTime,
FileSize = fileInfo.Length,
Width = (int)img.Width,
Height = (int)img.Height,
DirectoryName = fileInfo.DirectoryName,
FileCreationTime = fileInfo.CreationTime
});
}));
}
}
EDIT
<ScrollViewer Grid.Column="2">
<ListView x:Name="PhotoListView" BorderThickness="0"
ItemsSource="{Binding PhotoList, UpdateSourceTrigger=PropertyChanged}">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<controls:Tile Style="{StaticResource TileStyle}">
<StackPanel Background="White" Width="190" Height="140" Orientation="Vertical">
<Image Margin="5" Width="180" Height="110" Stretch="Fill" Source="{Binding BitmapImage}"/>
<TextBlock Text="{Binding ShortFileName}" TextAlignment="Center" Height="20" FontStyle="Italic" FontWeight="ExtraLight" Foreground="Black"></TextBlock>
</StackPanel>
</controls:Tile>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<EventSetter Event="MouseDoubleClick" Handler="ItemMouseDoubleClick"></EventSetter>
<EventSetter Event="PreviewMouseLeftButtonUp" Handler="ItemMouseClick"></EventSetter>
</Style>
</ListView.ItemContainerStyle>
</ListView>
</ScrollViewer>
I think binding isn't your main problem. You should check image caching. Try: Reloading an image in wpf

Infinity scroll bug with data template

After user get the end of longlistselector ItemRealized event fires items add successfully. But the button's tag is empty (for added items), for items that I got first time button's tag isn't null.
This is my xaml DataTemplate:
<DataTemplate x:Key="TitleSongDataTemplate" x:Name="Titledata">
<Border Background="{StaticResource PhoneForegroundBrush}" Margin="0,0,12,12">
<Grid x:Name="GridOfButtons" Background="{StaticResource PhoneForegroundBrush}" >
<Grid Margin="0, -6, -7, 0"
HorizontalAlignment="Right"
VerticalAlignment="Top" Height="81" Width="83">
<Button
Content=""
FontFamily="Segoe UI Symbol"
Style="{StaticResource RoundButton}"
x:Name="AddToMySongsButton"
Tag="{Binding Song}"
Background="{StaticResource PhoneBackgroundBrush}"
Click="AddToMySongsButton_Click"/>
</Grid>
<Grid
VerticalAlignment="Top"
HorizontalAlignment="Left"
Margin="-17,-6,0,0" Height="81" Width="95">
<Button FontFamily="Segoe UI Symbol"
Content=""
Style="{StaticResource RoundButton}" Margin="10,0,0,0"
x:Name="PlayButton"
Background="{StaticResource PhoneBackgroundBrush}"
Tag="{Binding Song}"
Click="PlayButton_Click"/>
</Grid>
<Grid
HorizontalAlignment="Center"
VerticalAlignment="Top"
Margin="69,-7,60,0" Height="82" Width="84">
<Button Style="{StaticResource RoundButton}"
Content=""
FontFamily="Segoe UI Symbol"
x:Name="DownloadButton"
Margin="-5,0,0,0"
Background="{StaticResource PhoneBackgroundBrush}"
Tag="{Binding Song}"
Click="DownloadButton_Click"/>
</Grid>
<StackPanel VerticalAlignment="Bottom">
<TextBlock Text="{Binding Title}" Foreground="{StaticResource PhoneBackgroundBrush}" Margin="6 , 4, 6, 4"/>
<TextBlock Text="{Binding Artist}" Foreground="Gray" Opacity="0.75" Margin="6, 0, 0, 6"/>
</StackPanel>
</Grid>
</Border>
</DataTemplate>
My pivot:
<phone:Pivot x:Name="MainTitle">
<phone:PivotItem Header="Rock">
<Grid>
<phone:LongListSelector x:Name="RockLongList"
GridCellSize="220,150"
LayoutMode="Grid"
ItemTemplate="{StaticResource TitleSongDataTemplate}"
ItemRealized="RockLongList_ItemRealized"/>
<TextBlock x:Name="RockText"
Text="Загрузка..."
FontSize="60"
Opacity="0.5"
Style="{StaticResource LongListSelectorGroupHeaderLetterTileStyle}"
Margin="0,10,10,10"
TextWrapping="Wrap"
HorizontalAlignment="Right"
Width="436"/>
</Grid>
</phone:PivotItem>
Here my infinity scrooling realization:
1.I fired ItemRealized
private void RockLongList_ItemRealized(object sender, ItemRealizationEventArgs e)
{
var nownum = offset + 50;
if (nownum >= usercount)
{
MainTitle.Title = "All songs've downloaded";
}
else
{
SpecialSongs.SongJSON song = e.Container.Content as SpecialSongs.SongJSON;
if (song != null)
{
int myoffset = 2;
// Only if there is no data that is currently getting loaded would be initiate the loading again
if (!isCurrentlyLoading && defaultBindList.Count - defaultBindList.IndexOf(song) <= myoffset)
{
LoadDataFromSource();
}
}
}
}
And finally:
private void LoadDataFromSource()
{
this.Dispatcher.BeginInvoke(() =>
{
MainTitle.Title = "Downloading test...";
});
//progressBar.IsVisible = true;
isCurrentlyLoading = true;
string UsersUri = string.Format("https://api.vk.com/method/audio.get?&count=50&access_token={0}&user_id={1}&version=4.92&offset={2}", AccessToken, uID, offset);
//var query = string.Format(datasourceUrl, currentPage);
WebClient client = new WebClient();
client.DownloadStringCompleted += client_DownloadStringCompleted;
client.DownloadStringAsync(new Uri(UsersUri));
}
private void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
//Here handle exception
using (var reader = new MemoryStream(Encoding.Unicode.GetBytes(e.Result)))
{
SpecialSongs songs = JsonConvert.DeserializeObject<SpecialSongs>(e.Result);
this.Dispatcher.BeginInvoke(() =>
{
foreach (var tracks in songs.songs)
{
rockBindList.Add(tracks);
MainTitle.Title = "Downloaded test...";
}
RockLongList.ItemsSource = rockBindList;
isCurrentlyLoading = false;
//progressBar.IsVisible = false;
});
}
offset += 50;
}
This code shows why i need button's tag property:
private void DownloadButton_Click(object sender, RoutedEventArgs e)
{
try
{
SpecialSongs.SongJSON songdgd = (SpecialSongs.SongJSON)(sender as Button).Tag;
this.Download.Message = songdgd.Artist + "\n" + songdgd.Title;
string StringToSave = "shared/transfers/" + songdgd.Artist + songdgd.Title;
var linktosave = StringToSave.Replace(" ", "");
transferRequest = new BackgroundTransferRequest(new Uri(songdgd.URI, UriKind.RelativeOrAbsolute)) { Method = "GET" };
var uri = new Uri(linktosave, UriKind.Relative);
songdgd.URI = linktosave.Replace("shared/transfers/", "");
var json = JsonConvert.SerializeObject(songdgd);
var name = linktosave.Replace("shared/transfers/", "");
transferRequest.Tag = "json" + json + "json" + "uri" + name + "uri";
transferRequest.TransferPreferences = TransferPreferences.AllowCellularAndBattery;
transferRequest.DownloadLocation = uri;
try
{
BackgroundTransferService.Add(transferRequest);
}
catch
{
MessageBox.Show("Эта песня уже загружается.");
}
}
catch { MessageBox.Show("Error while downloading"); }
}
Thanks.

GART Augmented Reality issue

I'm working with windows phone 8 apps and want to add augmented reality feature and I'm using GART, but I experiencing the same issue
in there and even there is a solution by Igor Ralic by adding canvas.zindex to 1, I'm still experiencing the same issue (the items in world view flicker and disappear), so maybe there is anybody in here that having much better solution? I'm using mvvm patern to work with this AR
Here is my approach with mvvm
This is my mainviewmodel
private ObservableCollection<ARItem> _ardisplayLocation = null;
public ObservableCollection<ARItem> ardisplayLocation
{
get { return _ardisplayLocation; }
set { this.SetProperty(ref this._ardisplayLocation, value); }
}
private void UpdateTransport()
{
try
{
myMessage = "Loading web server data...";
WebClient client = new WebClient();
Uri uri = new Uri(transportURL1 + latitude + "%2C" + longitude + transportURL2, UriKind.Absolute);
client.DownloadStringCompleted += (s, e) =>
{
MainPage mainpage = new MainPage();
mainpage.RefreshButton();
if (e.Error == null)
{
RootObject result = JsonConvert.DeserializeObject<RootObject>(e.Result);
hereRestProperty = new ObservableCollection<Item>(result.results.items);
for (int i = 0; i < hereRestProperty.Count; i++)
{
ardisplayLocation.Add(new CityPlace()
{
GeoLocation = new GeoCoordinate(hereRestProperty[i].coordinate.Latitude,hereRestProperty[i].coordinate.Longitude),
Content = hereRestProperty[i].title,
Description = hereRestProperty[i].vicinity
});
}
}
else
{
isFailed = Visibility.Visible;
myMessage = "Failed to load web server data, please refresh";
}
isBusy = false;
};
client.DownloadStringAsync(uri);
}
catch (Exception)
{
isBusy = false;
isFailed = Visibility.Visible;
myMessage = "Something wrong happen, please refresh";
}
}
and here is my ArDisplay.xaml.cs
private MainViewModel mvm { get { return this.DataContext as MainViewModel; } }
public ArDisplay()
{
InitializeComponent();
DataContext = App.ViewModel;
}
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
ardisplay.StartServices();
ardisplay.ARItems = mvm.ardisplayLocation;
base.OnNavigatedTo(e);
}
protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
{
ardisplay.StopServices();
base.OnNavigatedFrom(e);
}
and my xaml
<gart:ARDisplay Name="ardisplay" AttitudeRefreshRate="50" MovementThreshold="10">
<gart:VideoPreview x:Name="videoPreview" Canvas.ZIndex="1"/>
<gart:WorldView x:Name="worldView" Canvas.ZIndex="1" ItemTemplate="{StaticResource CityItemTemplate}" MinItemScale="0.1" MaxItemScale="1.0" FarClippingPlane="300.0" NearClippingPlane="1.0"/>
<gart:HeadingIndicator x:Name="headingIndicator" Canvas.ZIndex="1" Width="300" Height="300" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</gart:ARDisplay>
and my data template
<DataTemplate x:Key="CityItemTemplate">
<Border BorderBrush="Black" BorderThickness="4" CornerRadius="8" Background="#FF003847" Width="320">
<StackPanel Margin="4">
<TextBlock x:Name="NameBlock" TextWrapping="NoWrap" Text="{Binding Content}" FontSize="38" VerticalAlignment="Center" Margin="0,0,4,0" Grid.Column="1" TextTrimming="WordEllipsis"/>
<TextBlock x:Name="DescriptionBlock" TextWrapping="Wrap" Text="{Binding Description}" FontSize="24" VerticalAlignment="Center" Margin="0,0,4,0" Grid.Column="1" TextTrimming="WordEllipsis" MaxHeight="168"/>
</StackPanel>
</Border>
</DataTemplate>
Canvas.ZIndex was missing from your DataTemplate
<DataTemplate x:Key="CityItemTemplate">
<Border BorderBrush="Black" BorderThickness="4" CornerRadius="8" Background="#FF003847" Width="320" Canvas.ZIndex="2">
<StackPanel Margin="4">
<TextBlock x:Name="NameBlock" TextWrapping="NoWrap" Text="{Binding Content}" FontSize="38" VerticalAlignment="Center" Margin="0,0,4,0" Grid.Column="1" TextTrimming="WordEllipsis"/>
<TextBlock x:Name="DescriptionBlock" TextWrapping="Wrap" Text="{Binding Description}" FontSize="24" VerticalAlignment="Center" Margin="0,0,4,0" Grid.Column="1" TextTrimming="WordEllipsis" MaxHeight="168"/>
</StackPanel>
</Border>
</DataTemplate>

Categories