How to use OpenFileDialog in Wpf - wpf

I am using a WPF application. I am new to wpf but I have experience with Windows Forms. Wpf is great I want to learn how to programme with it. My problem is: I have written a code, I can use it but its not possible for me to use the OpenFileDialog function correctly. I want to read a csv txt file, structure of files are always the same only the rows are different. The name of the files is also different, I want to read and edit one file after the other. Read, edit, save. My Code is here:
public static class PersonService
public static List<Person> ReadFile(string filepath)
{
var lines = File.ReadAllLines(filepath);
var data = from l in lines.Skip(1)
let split = l.Split(';')
select new Person
{
Id = int.Parse(split[0]),
Name = split[1],
Age = int.Parse(split[2]),
Gender = (Gender)Enum.Parse(typeof(Gender), split[3])
};
return data.ToList();
}
}
public partial class Window2 : Window
public Window2()
{
InitializeComponent();
OpenFileDialog csv = new OpenFileDialog
DataContext = PersonService.ReadFile(csv);
<Window x:Class="WpfApplication14.Window2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window2" Height="300" Width="300">
<DataGrid AutoGenerateColumns="True"
ItemsSource="{Binding}"/>

This should look something like this:
//Create file dialog and configure to open csv files only
OpenFileDialog csvFielDialog = new OpenFileDialog();
csvFielDialog.Filter = "CSF files(*.csv)|*.csv";
//Show the dialog to the user
bool? result = csvFielDialog.ShowDialog();
//If the user selected something perform the actions with the file
if(result.HasValue && result.Value)
{
DataContext = PersonService.ReadFile(csvFielDialog.FileName);
}

Related

WPF Vector Printing - Send DrawingGroup as Vector to printer

I would like to use WPF to programmatically print. However, I need all the material to be sent to the printer in vector graphics and not raster graphics.
The main issue is, I cannot get WPF to print vector graphics, the prints always gets rasterized.
I useSharpVectors, which transforms an .svg file into am .xaml drawing group. And then insert that drawing group into an Image into a flowdocument, finally I send the flowdocument to print using an XPSDocumentWriter.
Blurry every time. I compare the print to the .svg file printed from adobe Illustrator. Night and day quality.
Is there any way to take a drawing group and always have it print as vector?
I am putting a bounty on this. You must submit the c# code necessary to send the following drawing group to the printer as vector graphics, this must be reproducible to get the bounty. Also, simply increasing the DPI after the image is rasterized does not qualify as an answer. No vector print - no bounty.
https://drive.google.com/file/d/0B-M6Yes83t08V0ZOOEp1Q3dEYjA/view?usp=sharing
Google Drive
DrawingGroup xaml
Yes you can ! ;-)
I think you'd better forget the image and use a FixedDocument
First create a class, overriding OnRender :
public partial class MapDrawingElement : FrameworkElement
{
public MapDrawingElement()
{
InitializeComponent();
}
protected override void OnRender(DrawingContext drawingContext)
{
base.OnRender(drawingContext);
var res = Resources["drawingGroup1"] as DrawingGroup;
if (res != null)
drawingContext.DrawDrawing(res);
}
}
The class has a drawingGroup1 Resource in its resource section :
<FrameworkElement x:Class="DemoFixedpageDocument.MapDrawingElement"
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"
mc:Ignorable="d"
d:DesignHeight="800" d:DesignWidth="800">
<FrameworkElement.Resources>
<DrawingGroup x:Key="drawingGroup1">
... here your xaml 16k lines ! ...
</DrawingGroup>
</FrameworkElement.Resources>
</FrameworkElement>
Instanciate a FixedDocument, and put the control with the map in a page :
public static class DocumentMaker
{
public static FixedDocument GenerateFixedDocument()
{
FixedDocument fixedDocument = new FixedDocument();
PageContent pageContent1 = new PageContent();
fixedDocument.Pages.Add(pageContent1);
FixedPage page1 = new FixedPage();
// PageContent : some text or an object can be added
((IAddChild)pageContent1).AddChild(page1);
MapDrawingElement elt = new MapDrawingElement();
page1.Children.Add(elt);
return fixedDocument;
}
}
Then you can print :
PrintDocumentImageableArea imageArea = null;
XpsDocumentWriter xpsdw = PrintQueue.CreateXpsDocumentWriter(ref imageArea);
if (xpsdw != null)
{
xpsdw.Write(DocumentMaker.GenerateFixedDocument());
}
You can also print preview or send to an XPS file.
See the working demo in the link :
http://1drv.ms/1RefeuJ
Regards

manipulate selected text on wpf webbrowser

I'm creating a epub books reader.
After displaying the book i want to allow users to add some annotation to the book.
To display the book, I'm using a wpf webbrowser control that loads local html files
I want to manipulate selected text on this control by creating a context menu or showing a popup
i've tried to change the control's contextmenu but by searching i found that isn't possible
this is an example of what i want to do with selected text:
IHTMLDocument2 htmlDocument = (IHTMLDocument2)webBrowser1.Document;
IHTMLSelectionObject currentSelection = htmlDocument.selection;
if (currentSelection != null)
{
IHTMLTxtRange range = currentSelection.createRange() as IHTMLTxtRange;
if (range != null)
{
MessageBox.Show(range.text);
}
}
WPF's native browser control will not let you set a custom context menu.
It gets even worse ; while your mouse is over the browser component, or if it has focus, it will not catch events generated by your input either.
A way around this, is to use the windows forms browser control inside a WindowsFormsHost.
To start, add Windows.Forms to your project references.
Then, do something like the following:
XAML:
<Window x:Class="blarb.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>
<WindowsFormsHost Name="windowsFormsHost" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"/>
</Grid>
</Window>
C# code:
public partial class MainWindow : Window
{
private System.Windows.Forms.WebBrowser Browser;
public MainWindow()
{
InitializeComponent();
//initialise the windows.forms browser component
Browser = new System.Windows.Forms.WebBrowser
{
//disable the default context menu
IsWebBrowserContextMenuEnabled = false
};
//make a custom context menu with items
System.Windows.Forms.ContextMenu BrowserContextMenu = new System.Windows.Forms.ContextMenu();
System.Windows.Forms.MenuItem MenuItem = new System.Windows.Forms.MenuItem {Text = "Take Action"};
MenuItem.Click += MenuItemOnClick;
BrowserContextMenu.MenuItems.Add(MenuItem);
Browser.ContextMenu = BrowserContextMenu;
//put the browser control in the windows forms host
windowsFormsHost.Child = Browser;
//navigate the browser like this:
Browser.Navigate("http://www.google.com");
}
private void MenuItemOnClick(object sender, EventArgs eventArgs)
{
//will be called when you click the context menu item
}
}
This does not yet explain how to do your highlighting though.
You could listen for the event fired by the browser component when it is done loading, and then replace portions of the document it loaded, injecting html code to do the highlighting.
Keep in mind that that might be tricky in some situations (when selecting text across divs, spans or paragraphs for example)
using mshtml;
private mshtml.HTMLDocumentEvents2_Event documentEvents;
in constructor or xaml set your LoadComplete event:
webBrowser.LoadCompleted += webBrowser_LoadCompleted;
then in that method create your new webbrowser document object and view the available properties and create new events as follows:
private void webBrowser_LoadCompleted(object sender, NavigationEventArgs e)
{
documentEvents = (HTMLDocumentEvents2_Event)webBrowserChat.Document; // this will access the events properties as needed
documentEvents.oncontextmenu += webBrowserChat_ContextMenuOpening;
}
private bool webBrowserChat_ContextMenuOpening(IHTMLEventObj pEvtObj)
{
return false; // ContextMenu wont open
// return true; ContextMenu will open
// Here you can create your custom contextmenu or whatever you want
}

open wpf window in Revit as add ins

I made a project using WPF and I want to open its window in Revit I trying windows form it worked but wpf not opened !!
I use this
public virtual Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
IDesign.MainWindow testsd = new IDesign.MainWindow();
testsd.InitializeComponent();
//MessageBox.Show("notworking");
return Result.Succeeded;
}
But it didn't work any solutions
public virtual Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
IDesign.MainWindow testsd = new IDesign.MainWindow();
//testsd.InitializeComponent();
//MessageBox.Show("notworking");
return Result.Succeeded;
}
public MainWindow()
{
InitializeComponent();
this.ShowDialog();
}
You may want to create a WPF User Control and assign it as the Content of a WPF window in a Revit External Command, something like:
UserControl1 userControl = new UserControl1();
Window win = new Window();
win.Content = userControl;
win.Show();

WPF & MVVM : Update an image field without breaking the pattern

I'm currently learning how to write a WPF application using the MVVM pattern. I'm writing a little contact manager application, so my app displays a Listbox bound to my View Model, and a set of fields bound to ListBox.SelectedItem. One of these fields is the contact's photo.
I'd like to change the photo in the edit part using OpenFileDialog, so the Listbox item would be updated, as it is for all of the other fields.
I first tried to update the source property of the Image control, but doing this, I lose the Binding...
Then I wrote an handler on Button_Click to update the Contact.Photo property (its type is byte[]), and it works. But instead of binding from the "update control" to the view model, binding is from the VM to the control, as if the data came from the DB.
(In the code, LoadPhoto returns a byte[])
private void Button_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog OpenFileDialog = new OpenFileDialog();
if (OpenFileDialog.ShowDialog() == true)
{
(listbox.SelectedItem as ContactManager.ViewModel.Contact).Photo =
LoadPhoto(OpenFileDialog.FileName);
}
}
I wonder if it doesn't break the MVVM pattern... I'm not sure of what could be made in the View... Is it the right way to update the Contact object ? Does anyone have a better solution to this problem ?
Look into binding your button to a Command Binding instead of the click event.
You can find implementations of DelegateCommand using Google.
Next you can expose a ImageSource from your ViewModel that you can bind to your Image from your XAML.
I've included some code fragments to get you started.
Once you get past the basics take a look at MVVM Frameworks, like Cinch, you'll find a way to handle OpenFileDialog using the Services Interfaces IOpenFileService.cs to not violate the MVVM pattern.
Here is the XAML:
<Button Content="Update Photo" Command="{Binding UpdatePictureCommand}"/>
<Image Source="{Binding EmployeePicture}"
VerticalAlignment="Center" HorizontalAlignment="Center"
Stretch="Fill" />
Here is the ViewModel:
public MainViewModel()
{
UpdatePictureCommand = new DelegateCommand<object>(OnUpdatePictureCommand, CanUpdatePictureCommand);
}
public ICommand UpdatePictureCommand { get; private set; }
private void OnUpdatePictureCommand(object obj)
{
OpenFileDialog OpenFileDialog = new OpenFileDialog();
if (OpenFileDialog.ShowDialog() == true)
{
//(listbox.SelectedItem as ContactManager.ViewModel.Contact).Photo =
// LoadPhoto(OpenFileDialog.FileName);
Stream reader = File.OpenRead(OpenFileDialog.FileName);
System.Drawing.Image photo = System.Drawing.Image.FromStream((Stream)reader);
MemoryStream finalStream = new MemoryStream();
photo.Save(finalStream, ImageFormat.Png);
// translate to image source
PngBitmapDecoder decoder = new PngBitmapDecoder(finalStream, BitmapCreateOptions.PreservePixelFormat,
BitmapCacheOption.Default);
EmployeePicture = decoder.Frames[0];;
}
private bool CanMoveFirstCommand(object obj)
{
return true;
}
private ImageSource _employeePicture;
public ImageSource EmployeePicture
{
get
{
return _employeePicture;
}
set
{
_employeePicture = value;
OnPropertyChanged("EmployeePicture");
}
}

Trying to understand details of the Application Resource assignment

I have a ComboBox with ItemsSource="{DynamicResource testResource}". The testResource is the Application resource that I set in C# code.
What I have noticed is that if I load Window befor Application created, the resource is not loaded by ComboBox:
Window window = (Window)LoadXaml("Window1.xaml");
Application app = new Application();
This code works
Application app = new Application();
Window window = (Window)LoadXaml("Window1.xaml");
Also, even if I created the window befor the application, I can load resource latter in button click handler.
Can some one explain, what happens? Why the order matters?
Window1.xaml:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<StackPanel>
<ComboBox ItemsSource="{DynamicResource testResource}" SelectedIndex="0"></ComboBox>
<Button x:Name='testButton'>Test</Button>
</StackPanel>
</Window>
C#
class Program
{
[STAThread]
public static void Main()
{
Window window = (Window)LoadXaml("Window1.xaml");
Application app = new Application();
SetupResource();
(window.FindName("testButton") as Button).Click += new RoutedEventHandler(testButton_Click);
window.Show();
app.Run(window);
}
static void testButton_Click(object sender, RoutedEventArgs e)
{
SetupResource();
}
static void SetupResource()
{
List<string> list = new List<string>();
list.Add("Hola");
list.Add("Mundo");
Application.Current.Resources["testResource"] = list;
}
static object LoadXaml(string fileName)
{
return XamlReader.Load(File.Open(fileName, FileMode.Open));
}
}
Not sure, but I would guess because the Application's Resources are only loaded when the Application object is created. So if you want to access testResource, you need to do it after the call to new Application().

Resources