MVVM: Image Bind Source from FileOpenPicker - c#

I added the OnActivated() into app.xaml.cs it is work correctly:
protected async override void OnActivated(IActivatedEventArgs args)
{
var continuationEventArgs = args as IContinuationActivatedEventArgs;
if (continuationEventArgs != null)
{
switch (continuationEventArgs.Kind)
{
case ActivationKind.PickFileContinuation:
FileOpenPickerContinuationEventArgs arguments = continuationEventArgs as FileOpenPickerContinuationEventArgs;
string passedData = (string)arguments.ContinuationData["keyParameter"];
StorageFile file = arguments.Files.FirstOrDefault(); // your picked file
addNewPlaceViewModel.OnFilesPicked(file);
// do what you want
break;
}
}
}
I hooked already FileOpenPicker into MVVM project correctly. This is my code:
private static readonly IEnumerable<string> SupportedImageFileTypes = new List<string> { ".jpeg", ".jpg", ".png" };
public AddNewPlaceViewModel(INavigationService navigationService)
{
this.navigationService = navigationService;
}
private async void OnFilesPicked(IStorageFile file)
{
if (file != null)
{
var bitmapImage = new BitmapImage();
await bitmapImage.SetSourceAsync(await file.OpenReadAsync());
Picture = bitmapImage;
//IN debugger in picture I have sht but in xaml i cannot show this.
}
}
}
private static void TriggerPicker(IEnumerable<string> fileTypeFilers, bool shouldPickMultiple = false)
{
var fop = new FileOpenPicker();
foreach (var fileType in fileTypeFilers)
{
fop.FileTypeFilter.Add(fileType);
}
if (shouldPickMultiple)
{
fop.PickMultipleFilesAndContinue();
}
else
{
fop.PickSingleFileAndContinue();
}
}
This is situation after Picture = bitmapImage;
I have also set up Binding and ICommand:
public ICommand UpdatePictureCommand
{
get { return new RelayCommand(o => TriggerPicker(SupportedImageFileTypes)); }
}
private ImageSource _Picture;
public ImageSource Picture
{
get
{
return _Picture;
}
set
{
_Picture = value;
OnPropertyChanged("Picture");
}
}
And this is my XAML in pivot item(button and Image) when I want to show photo which I have taken.
<Button Grid.Row ="4"
Content="Dodaj zdjęcie"
HorizontalAlignment="Center"
Command="{Binding UpdatePictureCommand}"/>
<Image Grid.Row="6"
Width="192"
Height="192"
Source="{Binding Picture, Mode=TwoWay}"
/>
A file open picker is working correctly(I can choose or take a photo) but after that I cannot see choosed/taked photo in my XAML. What is going wrong with that code?

you can create a converter something like this
[ValueConversion(typeof(Image), typeof(System.Windows.Media.ImageSource))]
public class ImageConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
{
return null;
}
var bitmap = (Bitmap)value;
return System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
bitmap.GetHbitmap(),
IntPtr.Zero,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return null;
}
}

Related

How to call C# event from javascript code?

I need to call C# event in xamarin.forms after the function is completed in js.Please guide
function readTextFile(file)
{
try
{
var blob = null;
var rawFile = new XMLHttpRequest();
rawFile.open(""GET"", file);
rawFile.responseType = ""blob"";//force the HTTP response, response-type header to be blob
rawFile.onload = function()
{
blob = rawFile.response;//xhr.response is now a blob object
wavesurfer.loadBlob(blob);
wavesurfer2.loadBlob(blob);
}
rawFile.send();//I need to call C# event here.Please guide.
}
catch(err)
{
}
}
Solution:
You can implement it by using CustomRenderer
1.create a HybridWebView in forms
public class HybridWebView : View
{
Action<string> action;
public static readonly BindableProperty UriProperty = BindableProperty.Create (
propertyName: "Uri",
returnType: typeof(string),
declaringType: typeof(HybridWebView),
defaultValue: default(string));
public string Uri {
get { return (string)GetValue (UriProperty); }
set { SetValue (UriProperty, value); }
}
public void RegisterAction (Action<string> callback)
{
action = callback;
}
public void Cleanup ()
{
action = null;
}
public void InvokeAction (string data)
{
if (action == null || data == null) {
return;
}
action.Invoke (data);
}
}
in contentPage.xaml
<ContentPage.Content>
<local:HybridWebView x:Name="hybridWebView" Uri="xxx.html"
HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" />
</ContentPage.Content>
in code behind
public MainPage ()
{
...
hybridWebView.RegisterAction (data => DisplayAlert ("Alert", "JS action has been called", "OK")); //you can do something other as you want
}
in iOS project
[assembly: ExportRenderer (typeof(HybridWebView), typeof(HybridWebViewRenderer))]
namespace xxx.iOS
{
public class HybridWebViewRenderer : ViewRenderer<HybridWebView, WKWebView>, IWKScriptMessageHandler
{
const string JavaScriptFunction = "function invokeCSharpAction(data){window.webkit.messageHandlers.invokeAction.postMessage(data);}";
WKUserContentController userController;
protected override void OnElementChanged (ElementChangedEventArgs<HybridWebView> e)
{
base.OnElementChanged (e);
if (Control == null) {
userController = new WKUserContentController ();
var script = new WKUserScript (new NSString (JavaScriptFunction), WKUserScriptInjectionTime.AtDocumentEnd, false);
userController.AddUserScript (script);
userController.AddScriptMessageHandler (this, "invokeAction");
var config = new WKWebViewConfiguration { UserContentController = userController };
var webView = new WKWebView (Frame, config);
SetNativeControl (webView);
}
if (e.OldElement != null) {
userController.RemoveAllUserScripts ();
userController.RemoveScriptMessageHandler ("invokeAction");
var hybridWebView = e.OldElement as HybridWebView;
hybridWebView.Cleanup ();
}
if (e.NewElement != null) {
string fileName = Path.Combine (NSBundle.MainBundle.BundlePath, string.Format ("Content/{0}", Element.Uri));
Control.LoadRequest (new NSUrlRequest (new NSUrl (fileName, false)));
}
}
public void DidReceiveScriptMessage (WKUserContentController userContentController, WKScriptMessage message)
{
Element.InvokeAction (message.Body.ToString ());
}
}
}
in Android project
[assembly: ExportRenderer(typeof(HybridWebView), typeof(HybridWebViewRenderer))]
namespace xxx.Droid
{
public class HybridWebViewRenderer : ViewRenderer<HybridWebView, Android.Webkit.WebView>
{
const string JavascriptFunction = "function invokeCSharpAction(data){jsBridge.invokeAction(data);}";
Context _context;
public HybridWebViewRenderer(Context context) : base(context)
{
_context = context;
}
protected override void OnElementChanged(ElementChangedEventArgs<HybridWebView> e)
{
base.OnElementChanged(e);
if (Control == null)
{
var webView = new Android.Webkit.WebView(_context);
webView.Settings.JavaScriptEnabled = true;
webView.SetWebViewClient(new JavascriptWebViewClient($"javascript: {JavascriptFunction}"));
SetNativeControl(webView);
}
if (e.OldElement != null)
{
Control.RemoveJavascriptInterface("jsBridge");
var hybridWebView = e.OldElement as HybridWebView;
hybridWebView.Cleanup();
}
if (e.NewElement != null)
{
Control.AddJavascriptInterface(new JSBridge(this), "jsBridge");
Control.LoadUrl($"file:///android_asset/Content/{Element.Uri}");
}
}
}
}
And
public class JavascriptWebViewClient : WebViewClient
{
string _javascript;
public JavascriptWebViewClient(string javascript)
{
_javascript = javascript;
}
public override void OnPageFinished(WebView view, string url)
{
base.OnPageFinished(view, url);
view.EvaluateJavascript(_javascript, null);
}
}
in your Html
function readTextFile(file)
{
try
{
var blob = null;
var rawFile = new XMLHttpRequest();
rawFile.open(""GET"", file);
rawFile.responseType = ""blob"";//force the HTTP response, response-type header to be blob
rawFile.onload = function()
{
blob = rawFile.response;//xhr.response is now a blob object
wavesurfer.loadBlob(blob);
wavesurfer2.loadBlob(blob);
}
rawFile.send();
invokeCSharpAction(data); //you can pass some params if you need
}
catch(err)
{
}
}
For more detail you can refer here .

UWP: Images in GridView cause memory leaks

I've developed an UWP app for managing forms. Each form can contain a lot of images. These images raise memory leaks, and I don't found any solution to fix this.
Currently all the datas are stored in a SQLite database, including the images, as byte[].
The root object is a "Car_Form", which contains the "Images" in an ObservableCollection:
public class Car_Forms : BasePoco
{
// form_id
private int _form_id;
[PrimaryKey, NotNull, AutoIncrement]
public int form_id
{
get
{ return _form_id; }
set
{
if (value != _form_id)
{
_form_id = value;
RaisePropertyChanged(() => form_id);
}
}
}
//...
// images
private ObservableCollection<Images> _images;
[Ignore]
public ObservableCollection<Images> images
{
get
{ return _images; }
set
{
if (value != _images)
{
_images = value;
RaisePropertyChanged(() => images);
}
}
}
}
The "Images" object contains the reference to the "Car_Form", the byte[] that is stored in the SQLite database in the "image1" field, and the BitmapImage that is used for the display, in the "image_display" field:
public class Images : BasePoco
{
// image_id
private int _image_id;
[PrimaryKey, NotNull, AutoIncrement]
public int image_id
{
get
{ return _image_id; }
set
{
if (value != _image_id)
{
_image_id = value;
RaisePropertyChanged(() => image_id);
}
}
}
//...
// image1
private byte[] _image1;
[NotNull]
public byte[] image1
{
get
{ return _image1; }
set
{
if (value != _image1)
{
_image1 = value;
RaisePropertyChanged(() => image1);
}
}
}
// form_id
private int? _form_id;
public int? form_id
{
get
{ return _form_id; }
set
{
if (value != _form_id)
{
_form_id = value;
RaisePropertyChanged(() => form_id);
}
}
}
// bitmap_image
private BitmapImage _bitmap_image;
[Ignore]
public BitmapImage bitmap_image
{
get
{ return _bitmap_image; }
set
{
if (value != _bitmap_image)
{
_bitmap_image = value;
RaisePropertyChanged(() => bitmap_image);
}
}
}
}
In my XAML page, the "Images" are in displayed in a GridView like this:
<GridView ItemsSource="{x:Bind ViewModel.CarForm.images, Mode=OneWay}"
IsItemClickEnabled="True"
SelectionMode="Single"
Grid.Row="1">
<GridView.ItemTemplate>
<DataTemplate x:DataType="models:Images">
<Border BorderBrush="Gray" BorderThickness="2"
Background="White"
Padding="10"
Height="160" Width="225">
<Image Stretch="UniformToFill"
Source="{x:Bind image1, Mode=OneWay, Converter={StaticResource ByteArrayToBitmapImageConverter}}" />
</Border>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
The datas are loaded from the SQLite database in the ViewModel:
private Car_Forms _carForm;
public Car_Forms CarForm
{
get { return _carForm; }
//set { Set(ref _carForm, value); }
set
{
this._carForm = value;
RaisePropertyChanged(() => CarForm);
}
}
private void LoadForm(Guid id)
{
CarForm = RepositoryService.GetById<Car_Forms>(id);
var formImages = RepositoryService.Where<Images>(im => im.IsDeleted == false && im.form_id == CarForm.form_id);
CarForm.images = new ObservableCollection<Images>(formImages);
//...
}
Then, the the BitmapImage is loaded through the "ByteArrayToBitmapImageConverter":
public class ByteArrayToBitmapImageConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
try
{
var bImg = (byte[])value;
if (bImg != null)
{
BitmapImage biImg = ByteArrayBitmapHelper.AsBitmapImage(bImg);
return biImg;
}
else
{
return null;
}
}
catch (Exception e)
{
return null;
}
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
return null;
}
}
public static BitmapImage AsBitmapImage(this byte[] byteArray)
{
if (byteArray != null)
{
using (var stream = new InMemoryRandomAccessStream())
{
stream.WriteAsync(byteArray.AsBuffer()).GetResults();
var image = new BitmapImage();
stream.Seek(0);
image.SetSource(stream);
return image;
}
}
return null;
}
I have also implemented a "Cleanup()" method on the ViewModel, where I "clean" all the objects that are used:
public override void Cleanup()
{
//...
CarForm.images.Clear();
CarForm = null;
base.Cleanup();
}
But when I launch the app, I can see that all resources are not released: each time that I open the same form and that I come back to the list, there are 30 Mo that are not released.
laucnh of the app: "Home" page
display of the form
back to the "Home" page
display of the form
back to the "Home" page
display of the form
display of the form
back to the "Home" page
display of the form
=> Would you have any explanation? How could I optimize it?
This is happening because pages in UWP are not cached by default, so everytime you navigate to page, new instance of that page is created. You can set the NavigationCacheMode property of the page to NavigationCacheMode.Required so the pages will be cached and navigation will not be causing memory leaks.

Xamarin forms, how do I expose the underlying imagedata that my current code does not get?

I have created a viewmodel that I connect to my current page where the user selects an image from his phonealbum.
When I pick a image it works perfectly fine and the picture appears on the screen just how I want but when I try to store it on my database I get a crash and I think it is (as I have been told) that it is due to the fact that my code does not get the imagedata.
Apparently there is a package called Xamarin.Plugin.Media and I have been fooling around a bit with that but with no luck.
This is my code:
My viewmodel:
public class CameraViewModel : ViewModel
{
private readonly TaskScheduler _scheduler = TaskScheduler.FromCurrentSynchronizationContext();
private IMediaPicker _Mediapicker;
private ImageSource _ImageSource;
private string _VideoInfo;
private Command _TakePictureCommand;
private Command _SelectPictureCommand;
private Command _SelectVideoCommand;
private string _Status;
public CameraViewModel()
{
Setup ();
}
public ImageSource ImageSource
{
get { return _ImageSource; }
set { SetProperty (ref _ImageSource, value); }
}
public string VideoInfo
{
get { return _VideoInfo; }
set { SetProperty (ref _VideoInfo, value); }
}
public Command TakePictureCommand
{
get {
return _TakePictureCommand ?? (_TakePictureCommand =
new Command (async () => await TakePicture (), () => true));
}
}
public Command SelectPictureCommand
{
get {
return _SelectPictureCommand ?? (_SelectPictureCommand =
new Command (async () => await SelectPicture (), () => true));
}
}
public Command SelectVideoCommand
{
get {
return _SelectVideoCommand ?? (_SelectVideoCommand =
new Command (async () => await SelectVideo (), () => true));
}
}
public string Status
{
get { return _Status; }
set { SetProperty (ref _Status, value); }
}
private void Setup()
{
if (_Mediapicker == null) {
var device = Resolver.Resolve<IDevice> ();
_Mediapicker = DependencyService.Get<IMediaPicker> () ?? device.MediaPicker;
}
}
public async Task<MediaFile> TakePicture()
{
Setup ();
ImageSource = null;
return await _Mediapicker.TakePhotoAsync (new CameraMediaStorageOptions {
DefaultCamera = CameraDevice.Front, MaxPixelDimension = 400
}).ContinueWith (t => {
if (t.IsFaulted)
{
Status = t.Exception.InnerException.ToString();
}
else if (t.IsCanceled)
{
Status = "Canceled";
}
else
{
var mediaFile = t.Result;
ImageSource = ImageSource.FromStream(() => mediaFile.Source);
return mediaFile;
}
return null;
}, _scheduler);
}
public async Task SelectPicture()
{
Setup ();
ImageSource = null;
try
{
var mediaFile = await _Mediapicker.SelectPhotoAsync(new CameraMediaStorageOptions
{
DefaultCamera = CameraDevice.Front,
MaxPixelDimension = 400
});
VideoInfo = mediaFile.Path;
ImageSource = ImageSource.FromStream(() => mediaFile.Source);
}
catch (System.Exception ex)
{
Status = ex.Message;
}
}
public async Task SelectVideo()
{
Setup ();
VideoInfo = "Selecting video";
try
{
var mediaFile = await _Mediapicker.SelectVideoAsync(new VideoMediaStorageOptions());
VideoInfo = mediaFile != null
? string.Format("Your video size {0} MB", ConvertBytesToMegabytes(mediaFile.Source.Length))
: "No video was selected";
}
catch (System.Exception ex)
{
if (ex is TaskCanceledException) {
VideoInfo = "Selecting video cancelled";
} else {
VideoInfo = ex.Message;
}
}
}
private static double ConvertBytesToMegabytes(long bytes)
{
double rtn_value = (bytes / 1024f) / 1024f;
return rtn_value;
}
}
}
the Page that i am using:
CameraViewModel cameraOps = null;
public startPage ()
{
InitializeComponent ();
cameraOps = new CameraViewModel ();
}
private async void btnPickPicture_Clicked (object sender, EventArgs e)
{
await cameraOps.SelectPicture ();
imgPicked.Source = cameraOps.ImageSource;
}
So when I try to add my ImgPicked (Image in my XAML) in my database, it crashes. (Tell me if you would like to see the database-code as well)
And the crash says: Self referencing loop detected for property 'Member' with type 'System.Reflection.MonoMethod'. Path 'thePicture.Stream.Method.ReturnParameter'.
thePicture is where I try to store my image in my database.
The Media plugin returns a MediaFile object that has a couple of properties/methods you can use.
public string Path
is a property gives you the Path to the image file. You can use that to read the image data with File.ReadAllBytes() or some other method.
public Stream GetStream()
is a method that returns a stream with the image data. You can convert that stream to a byte array that will contain the image data.
You can use either of these in your ViewModel to get the byte[] data for the image, and later pass that data to your database calls.
You could modify your ViewModel to store the byte array for the image by doing something like this (untested)
private byte[] imageData;
public byte[] ImageData { get { return imageData; } }
private byte[] ReadStream(Stream input)
{
byte[] buffer = new byte[16*1024];
using (MemoryStream ms = new MemoryStream())
{
int read;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, read);
}
return ms.ToArray();
}
}
public async Task SelectPicture()
{
Setup ();
ImageSource = null;
try
{
var mediaFile = await _Mediapicker.SelectPhotoAsync(new CameraMediaStorageOptions
{
DefaultCamera = CameraDevice.Front,
MaxPixelDimension = 400
});
VideoInfo = mediaFile.Path;
// store the image data in a local variable
imageData = ReadStream(mediaFile.GetStream());
ImageSource = ImageSource.FromStream(() => mediaFile.Source);
}
catch (System.Exception ex)
{
Status = ex.Message;
}
}

MVC 4: Create new Razor View from string not from file path

The way to create Razor View from the code currently is to find a file using path parameters.
RazorView viewResult = new RazorView(ControllerContext, viewPath, layoutPath, boolRunViewStartPages, IEnumerableViewStartFileExtensions);
I do not want to get the view from file, i want to get the view from my database string. How can i achieve this:
RazorView viewResult = new RazorView(ControllerContext, stringViewHtml);
I do not want to use Virtual Path Provider because it will change all of my routing system, but if is there a way that i can only activate VPP when im creating the razor view, it will be appreciated!
Its been a while since I got the solution, I will share it here:
public static string RenderRazorViewToString(string viewToRender, object model, string controllerName, string loadAction, HttpContextBase httpContext, List<FormViewBags> viewData, string formModelType)
{
string view = "";
//Creating the view data
ViewDataDictionary ViewData = new ViewDataDictionary();
//The type of model used for this view
Type modelType = Helper.GetModelType(formModelType);
//Compiling the object model from parameter with the correct type
ViewData.Model = Cast(model, modelType);
if ((ViewData.Model != null) && (viewData != null))
{
//Adding view bags for the view
foreach (FormViewBags item in viewData)
{
ViewData.Add(item.Key, item.Value);
}
}
//The controller used to all this view
Type controllerType = Helper.GetModelType(controllerName);
//Creating the controller
object controller = Activator.CreateInstance(controllerType);
//Setting the routing
RouteData rd = new System.Web.Routing.RouteData();
rd.Values.Add("controller", controllerName.Split('.').Last().Replace("Controller",""));
//rd.Values.Add("action", loadAction);
//Setting the controller with corresponding context
((ControllerBase)(controller)).ControllerContext = new ControllerContext(httpContext, rd, (ControllerBase)controller);
ControllerContext cc = ((ControllerBase)(controller)).ControllerContext;
using (var sw = new StringWriter())
{
//The custom view engine I used to get the view
var engine = ViewEngines.Engines.Where(s => s.ToString().Equals("MyApp.App_Start.CustomViewEngine")).SingleOrDefault();
if (engine == null) throw new Exception("no viewengine");
//Finding the string/text of the view. My website use VPP to get view from database.
var viewResult = engine.FindPartialView(cc, viewToRender, false);
var viewContext = new ViewContext(cc, viewResult.View, ViewData, cc.Controller.TempData, sw);
//This code here renders all the information above into the real compiled string view
viewResult.View.Render(viewContext, sw);
viewResult.ViewEngine.ReleaseView(cc, viewResult.View);
view = sw.GetStringBuilder().ToString();
}
//Returns the string of the compiled view
return view;
}
This is my custom view engine:
public class CustomViewEngine : RazorViewEngine
{
private List<string> _plugins = new List<string>();
public CustomViewEngine(List<string> pluginFolders)
{
_plugins = pluginFolders;
ViewLocationFormats = GetViewLocations();
MasterLocationFormats = GetMasterLocations();
PartialViewLocationFormats = GetViewLocations();
}
public string[] GetViewLocations()
{
var views = new List<string>();
views.Add("~/Views/{1}/{0}.cshtml");
foreach (string p in _plugins)
{
views.Add("~/Modules/" + p + "/Views/{1}/{0}.cshtml");
}
return views.ToArray();
}
public string[] GetMasterLocations()
{
var masterPages = new List<string>();
masterPages.Add("~/Views/Shared/{0}.cshtml");
foreach (string p in _plugins)
{
masterPages.Add("~/Modules/" + p + "/Views/Shared/{0}.cshtml");
}
return masterPages.ToArray();
}
}
You need to use VPP (Virtual Path Provider) to automatically:
/* VIRTUAL PATH HELPER */
public class ViewPathProvider : VirtualPathProvider
{
//private static FormDBContext dbForm = new FormDBContext();
public override bool FileExists(string virtualPath)
{
return IsExistByVirtualPath(virtualPath) || base.FileExists(virtualPath);
}
public override VirtualFile GetFile(string virtualPath)
{
if (IsExistByVirtualPath(virtualPath))
{
return new ViewFile(virtualPath);
}
return base.GetFile(virtualPath);
}
public override CacheDependency GetCacheDependency(string virtualPath, System.Collections.IEnumerable virtualPathDependencies, DateTime utcStart)
{
if (IsExistByVirtualPath(virtualPath)) {
//return null; //return null to force no cache
return ViewCacheDependencyManager.Instance.Get(virtualPath); //uncomment this to enable caching
}
return Previous.GetCacheDependency(virtualPath, virtualPathDependencies, utcStart);
}
public override String GetFileHash(String virtualPath, IEnumerable virtualPathDependencies) //uncomment this getfilehash to turn on cache
{
if (IsExistByVirtualPath(virtualPath))
{
return Guid.NewGuid().ToString();
}
return Previous.GetFileHash(virtualPath, virtualPathDependencies);
}
public bool IsExistByVirtualPath(string virtualPath)
{
bool isExist = false;
try
{
string checker = virtualPath.First().Equals('~') ? virtualPath : "~" + virtualPath;
if (checker.IndexOf("/Views/", StringComparison.OrdinalIgnoreCase) > 0)
{
checker = "~" + Helper.RemoveSubfolderName(checker);
}
using (FormDBContext formsDB = new FormDBContext())
{
List<Form> f = formsDB.Forms.Where(m => m.VirtualPath.Equals(checker, StringComparison.CurrentCultureIgnoreCase)).ToList();
if ((f != null) && (f.Count > 0))
{
isExist = true;
base.GetFile(virtualPath);
}
}
}
catch (Exception ex)
{
Helper.Log("Is Exist By Virtual Path: " + ex);
}
return isExist;
}
}
public class VirtualForm
{
//private FormDBContext dbForm = new FormDBContext();
public string GetByVirtualPath(string virtualPath)
{
using (FormDBContext dbForm = new FormDBContext())
{
string content = string.Empty;
string checker = virtualPath.First().Equals("~") ? virtualPath : "~" + virtualPath;
if (checker.IndexOf("/Views/", StringComparison.OrdinalIgnoreCase) > 0)
{
checker = "~" + Helper.RemoveSubfolderName(checker);
}
Form f = dbForm.Forms.Where(m => m.VirtualPath.Equals(checker, StringComparison.CurrentCultureIgnoreCase)).First();
content = f.Html;
return content;
}
}
}
public class ViewFile : VirtualFile
{
private string path;
public ViewFile(string virtualPath)
: base(virtualPath)
{
path = virtualPath;
}
public override Stream Open()
{
if (string.IsNullOrEmpty(path))
return new MemoryStream();
VirtualForm vf = new VirtualForm();
string content = vf.GetByVirtualPath(path);
if (string.IsNullOrEmpty(content))
return new MemoryStream();
return new MemoryStream(ASCIIEncoding.UTF8.GetBytes(content));
}
}
public class ViewCacheDependencyManager
{
private static Dictionary<string, ViewCacheDependency> dependencies = new Dictionary<string, ViewCacheDependency>();
private static volatile ViewCacheDependencyManager instance;
private static object syncRoot = new Object();
private ViewCacheDependencyManager()
{
}
public static ViewCacheDependencyManager Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
{
instance = new ViewCacheDependencyManager();
}
}
}
return instance;
}
}
public CacheDependency Get(string virtualPath)
{
if (!dependencies.ContainsKey(virtualPath))
dependencies.Add(virtualPath, new ViewCacheDependency(virtualPath));
/*else //This else will always reset cache when it is virtual path
{
dependencies.Remove(virtualPath);
dependencies.Add(virtualPath, new ViewCacheDependency(virtualPath));
}*/
return dependencies[virtualPath];
}
public void Invalidate(string virtualPath)
{
string vp = virtualPath.First().Equals('~') ? virtualPath.Remove(0, 1) : virtualPath;
if (dependencies.ContainsKey(vp))
{
var dependency = dependencies[vp];
dependency.Invalidate();
dependency.Dispose();
dependencies.Remove(vp);
}
}
public void InvalidateAll()
{
dependencies.Clear();
}
}
public class ViewCacheDependency : CacheDependency
{
public ViewCacheDependency(string virtualPath)
{
base.SetUtcLastModified(DateTime.UtcNow);
}
public void Invalidate()
{
base.NotifyDependencyChanged(this, EventArgs.Empty);
}
}

How to find a Image using Image name(String) in Silverlight

I have created a page which contains several controls, in this i have to get a image which is in the page. I have the image name as string value. I have made a for loop to find the image and return, but it is tedious while looping all the controls in the page if it is more and it is getting much time too.
// Passing the string and find as image
Image imgBack = FindControl<Image>((UIElement)Layout, typeof(Image), strSelectedimg);
// Function to find image
public T FindControl<T>(UIElement parent, Type targetType, string ControlName) where T : FrameworkElement
{
if (parent == null) return null;
if (parent.GetType() == targetType && ((T)parent).Name == ControlName)
{
return (T)parent;
}
T result = null;
int count = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < count; i++)
{
UIElement child = (UIElement)VisualTreeHelper.GetChild(parent, i);
if (FindControl<T>(child, targetType, ControlName) != null)
{
result = FindControl<T>(child, targetType, ControlName);
break;
}
}
return result;
}
Is there any other easy way to find the image in the page using the string value.?
If you use the Silverlight Toolkit, then you don't need this maintain this helper method yourself, because it comes with a similar one already as an extension method.
using System.Linq;
using System.Windows.Controls.Primitives;
// ...
private void DoStuff()
{
var myImage = this.MyRootLayoutPanel.GetVisualDescendants().OfType<Image>()
.Where(img => img.Name == "MyImageName").FirstOrDefault();
}
Alternatively, I don't know your exact scenario, but if you're crafting a properly templated Control rather than a simple UserControl or Page, you'd just do
public class MyFancyControl : Control
{
public MyFancyControl()
{
this.DefaultStyleKey = typeof(MyFancyControl);
}
// ...
public override void OnApplyTemplate()
{
var myImage = this.GetTemplateChild("MyImageName") as Image;
}
}
Perhaps you could build a lookup at the same time you're adding the images. If you post your code that adds the images at runtime, I could give you a more exact answer; but I'm thinking something like this:
private Dictionary<string, Image> _imageLookup;
private class ImageInfo
{
public string Name { get; set; }
public string Uri { get; set; }
}
private void AddImages(ImageInfo[] imageInfos)
{
this._imageLookup = new Dictionary<string, Image>();
foreach (var info in imageInfos)
{
var img = CreateImage(info.Name, info.Uri);
if (!this._imageLookup.ContainsKey(info.Name))
{
this._imageLookup.Add(info.Name, img);
}
AddImageToUI(img);
}
}
private Image CreateImage(string name, string uri)
{
// TODO: Implement
throw new NotImplementedException();
}
private void AddImageToUI(Image img)
{
// TODO: Implement
throw new NotImplementedException();
}
Then you could easily find the image later:
public Image FindControl(string strSelectedImg)
{
if (this._imageLookup.ContainsKey(strSelectedImg))
{
return this._imageLookup[strSelectedImg];
}
else
{
return null; // Or maybe throw exception
}
}
If you need to find more than just images, you could use a Dictionary<string, Control> or Dictionary<string, UIElement> instead.

Categories

Resources