DialogResult in F# - wpf

Trying to retrieve a DialogResult from a window in a MVVM app, I stumbled on this previous question. After implementing the suggested changes, the sample looks like:
type DialogCloser() =
static let DialogResultProperty =
DependencyProperty.RegisterAttached("DialogResult", typeof<bool>, typeof<DialogCloser>, new PropertyMetadata(DialogResultChanged))
static member GetDialogResult (a:DependencyObject) =
a.GetValue(DialogResultProperty) :?> bool
static member SetDialogResult (a:DependencyObject) (value:string) =
a.SetValue(DialogResultProperty, value)
member this.DialogResultChanged (a:DependencyObject) (e:DependencyPropertyChangedEventArgs) =
let window = a :?> Window
match window with
| null -> failwith "Not a Window"
| _ -> window.DialogResult <- System.Nullable (e.NewValue :?> bool)
Now DialogResultChanged is used before it is declared, which of course doesn't compute in F#.
I can't seem to find a working solution, any help would be appreciated .

I'm not a WPF expert, but in this related C# solution, the DialogResultsChanged method is static. If you define the method as static in F# too, you should be able to reference it before it is declared (using the full name DialogCloser.DialogResultsChanged), so something like the following should do the trick:
type DialogCloser() =
static let DialogResultProperty =
DependencyProperty.RegisterAttached
( "DialogResult", typeof<bool>, typeof<DialogCloser>,
new PropertyMetadata(DialogCloser.DialogResultChanged))
static member GetDialogResult (a:DependencyObject) =
a.GetValue(DialogResultProperty) :?> bool
static member SetDialogResult (a:DependencyObject) (value:string) =
a.SetValue(DialogResultProperty, value)
static member DialogResultChanged
(a:DependencyObject) (e:DependencyPropertyChangedEventArgs) =
let window = a :?> Window
match window with
| null -> failwith "Not a Window"
| _ -> window.DialogResult <- System.Nullable (e.NewValue :?> bool)

Related

LINQ to SQL query to populate ListBox returns wrong results

Hello here's a LINQ to SQL query :
private void Stk_DT_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
DataTable dt = new DataTable();
DataGrid grid = sender as DataGrid;
#region Buttons Picking Libres
using(BdCretsDataContext dc=new BdCretsDataContext())
{
var placement = (from p in dc.PICKING
where p.ART_CODE == ArtCode_TxtBox.Text
select new { p.R_PLACEMENT }).Distinct().ToList();
LB.ItemsSource = placement;
}
#endregion
}
With this query I want to fill a ListBox. But I get this result :
All I want is just: 53.
Thanks for helping me
The point is that select new { p.R_PLACEMENT } creates a collection of objects that have a property called R_PLACEMENT. The ToString() of this object, which is invoked by the ListBox, returns a string representation of this object: { R_PLACEMENT = 53 }. You have to unwrap or collect the values from this property:
LB.ItemsSource = placement.Select(row => row.R_PLACEMENT);
This returns a collection of values only.
This is because you create a new (anonymous) type within select new { p.R_PLACEMENT }.
Your placement variable will thus hold a List<> of this new type. The ListBox however does not know how to display items of this type.
To make the ListBox display something useful you must tell it what it should make out of this anonymous type. ListBox does not figure out it on its own.
The simplest solution would probably be to create placement like this:
var placement = (from p in dc.PICKING
where p.ART_CODE == ArtCode_TxtBox.Text
select p.R_PLACEMENT.ToString()).Distinct().ToList();
(From your example I deduce that R_PLACEMENT is of some numeric type.) The .ToString() suffix makes placement a List<string> which the ListBox will be glad to display correctly.

Unable to cast object of type '<>f__AnonymousType0`2[System.String,System.Int32]' to type 'System.IConvertible'

I am trying to populate a data list box to text box on list box's click event but I found this error
Additional information: Unable to cast object of type '<>f__AnonymousType0`2[System.String,System.Int32]' to type 'System.IConvertible'
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
StudenRecordDataContext std = new StudentRecordDataContext();
int selectedValue = Convert.ToInt32(listBox1.SelectedValue);
StudentRecord sr = std.StudentRecords.Single(s =>s.ID==selectedValue);
txtId.Text = sr.ID.ToString();
txtName.Text = sr.Name;
txtPassword.Text = sr.Password;
txtCnic.Text = sr.CNIC;
txtEmail.Text = sr.Email;
}
I think the error is on line StudentRecord sr = std.StudentRecords.Single(s =>s.ID==selectedValue);
Where does that error come from and what do I need to change to fix that error?
I'm sorry to say so but you provided us with the wrong diagnosis of the line your program fails.
The culprit is this line:
int selectedValue = Convert.ToInt32(listBox1.SelectedValue);
I expect you have earlier populated that listbox1 with a collection from StudentRecords coming from an instance of your StudentRecordDataContext.
If you select a value from the listbox the SelectedValue holds the object you added to the items collection (or indirectly by setting the DataSource property).
To fix your code you could first make sure the object becomes a StudentRecord again. That is not that easy because you created an anonymous type, I expect something like:
listbox1.DataSource = new StudentRecordDataContext()
.StudentRecords
.Select(sr => new { Name = sr.Name, ID = sr.ID });
When you try to retrieve the SelectedValue you get that anonymous type, not something that is strongly typed.
Instead of adding an anonymous type, create a new class that has the properties for the Name and the Id:
class StudentRecordItem
{
public string Name {get; set;}
public int ID {get; set;}
}
When you populate the Datasource create StudentRecordItem classes for each record and add those to the datasource.
listbox1.DataSource = new StudentRecordDataContext()
.StudentRecords
.Select(sr => new StudentRecordItem { Name = sr.Name, ID = sr.ID });
The your code can become something like this:
StudentRecordItem selectedStudent = listBox1.SelectedValue as StudentRecordItem;
if (selectedStudent == null)
{
MessageBox.Show("No student record");
return;
}
int selectedValue = selectedStudent.ID;
You don't need the Convert.ToInt32 because I assume ID is already an int.
Remember that the debugger in Visual Studio shows the actual types and values of all your properties and variables. When a type conversion fails you can inspect there what the actual type is you're working with.

Exception Using Dynamically adding controls to silverlight childwindow?

I have a parameterised constructor in My Application. I want to add controls dynamically to my silverlight Child Control Page. But it gives NullReferenceException.
I can't find out why it returns null.Can any help me with this situation?
public PDFExport(FrameworkElement graphTile1, FrameworkElement graphTile2,FrameworkElement graphTile3)
{
Button btnGraph1 = new Button();
string Name = graphTile1.Name;
btnGraph1.Content = Name;
btnGraph1.Width = Name.Length;
btnGraph1.Height = 25;
btnGraph1.Click += new RoutedEventHandler(btnGraph1_Click);
objStack.Children.Add(btnGraph1);
LayoutRoot.Children.Add(objStack); // Here am getting null Reference Exception
_graphTile1 = graphTile1;
_graphTile2 = graphTile2;
_graphTile3 = graphTile3;
}
Thanks.
I guess objStack is a stackpanel declared in your XAML?
Be aware that the UI component of your xaml are build by the call to InitializeComponent.
Thus objStack will not exist until you call InitializeCOmponent() in your constructor.
Also, you should know that the call to InitializeComponent is asynchronous, so you code should look like something like that:
private readonly FrameworkElement _graphTile1;
private readonly FrameworkElement _graphTile2;
private readonly FrameworkElement _graphTile3;
public PDFExport(FrameworkElement graphTile1, FrameworkElement graphTile2, FrameworkElement graphTile3)
{
_graphTile1 = graphTile1;
_graphTile2 = graphTile2;
_graphTile3 = graphTile3;
}
private void PDFExport_OnLoaded(object sender, RoutedEventArgs e)
{
Button btnGraph1 = new Button();
string Name = _graphTile1.Name;
btnGraph1.Content = Name;
btnGraph1.Width = Name.Length;
btnGraph1.Height = 25;
btnGraph1.Click += new RoutedEventHandler(btnGraph1_Click);
objStack.Children.Add(btnGraph1);
LayoutRoot.Children.Add(objStack);
}
Hope it helps.
As per my research i got that, why it raises an exception: Because there is no
InitializeComponent() in My Constructor and am not calling parent constructor.
That is the reason it raises Exception.
Just Add InitializeComponent() to the code, simple

FSI WPF Event Loop

Is the WPF event loop in this answer still a good one for FSI (besides rethrow which is now reraise)? The answer is from 2008 and I'm not sure if there are any "better" implementations around. If not what would one be?
My understanding is that the default implementation is for WinForms.
Yes the default is for Winforms, I do use the WpfEventLoop quite a lot, Code is below,
#I "c:/Program Files/Reference Assemblies/Microsoft/Framework/v3.0"
#I "C:/WINDOWS/Microsoft.NET/Framework/v3.0/WPF/"
#r "PresentationCore.dll"
#r "PresentationFramework.dll"
#r "WindowsBase.dll"
module WPFEventLoop =
open System
open System.Windows
open System.Windows.Threading
open Microsoft.FSharp.Compiler.Interactive
open Microsoft.FSharp.Compiler.Interactive.Settings
type RunDelegate<'b> = delegate of unit -> 'b
let Create() =
let app =
try
// Ensure the current application exists. This may fail, if it already does.
let app = new Application() in
// Create a dummy window to act as the main window for the application.
// Because we're in FSI we never want to clean this up.
new Window() |> ignore;
app
with :? InvalidOperationException -> Application.Current
let disp = app.Dispatcher
let restart = ref false
{ new IEventLoop with
member x.Run() =
app.Run() |> ignore
!restart
member x.Invoke(f) =
try
disp.Invoke(DispatcherPriority.Send,new RunDelegate<_>(fun () -> box(f ()))) |> unbox
with e -> eprintf "\n\n ERROR: %O\n" e; reraise()
member x.ScheduleRestart() = ()
//restart := true;
//app.Shutdown()
}
let Install() = fsi.EventLoop <- Create()
WPFEventLoop.Install()
Test code
open System
open System.Windows
open System.Windows.Controls
let window = new Window(Title = "Simple Test", Width = 800., Height = 600.)
window.Show()
let textBox = new TextBox(Text = "F# is fun")
window.Content <- textBox
Let me know if this helps.
-Fahad

how to get the region name?

using Silverlight & Prism.
i create a new scoped region inside a TabControl like so:
IRegionManager regionManager = tabControl.Add(viewRegions, UNIQUEID, true);
then from the TabControl SelectionChanged event i want to get the name of that region.
so i go:
TabItem item = e.AddedItems[0] as TabItem;
FrameworkElement view = item.Content as FrameworkElement;
IRegionManager xxx = RegionManager.GetRegionManager(view);
so now i have the scoped region manager at hand = xxx!
but how do i get its name? (the "UNIQUEID" param i have assigned to it ).
HOW?
If you have the RegionManager, and the View, then you can get the region Name (but I don't know why you'd ever want to). If you loop through the regionmanger like this you can get what you want. You'll have to keep a reference around to the scoped RegionManager, but there's no way around that. (There is some extra code demonstrating other things that someone might want to do too)
private void UnloadRegion()
{
foreach (IRegion region in xxx.Regions)
{
for (int ix = region.ActiveViews.Count() - 1; ix >= 0; ix--)
{
if (WhateverYourCurrentViewIs == region.ActiveViews.Last())
{
string RegionName = region.Name;
//there is the name
{
}
}
}

Resources