-
-
Notifications
You must be signed in to change notification settings - Fork 71
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WPF DataTemplate X:Type receiving "Elmish.WPF.ViewModel'2[System.Object.System.Object]" #270
Comments
Elmish.WPF returns its internal "Details" |> Binding.subModelSeq((fun m -> m.Details), (fun detail -> detail.id), fun () ->
[
"Id" |> Binding.oneWay (fun (_, detail) -> detail.id)
"Name" |> Binding.oneWay (fun (_, detail) -> detail.name)
"Content" |> Binding.oneWay (fun (_,detail) -> detail.content)
]) When you use any If you have only one-way bindings and want to return a sequence of custom types, simply do: "Details" |> Binding.oneWay(fun m -> m.Details) Or even better, use Note that you can't have anything other than one-way bindings in this way. |
Please try to follow the steps in #268 (comment) so you can share a branch with this code that has the behavior you describe. |
@cmeeren When doing as you advised, I now am losing the "Name" resolution needed for the tab: BindingExpression path error: 'Name' property not found on 'object' ''ContactDetail' My TabItem Header is now blank??? |
We will be better able assist you if you are able to share a branch with this code that has the behavior you describe. |
@cmeeren I'm guessing what I need is something that functions like this: "Details" |> Binding.oneWay(fun m -> m.Details)
|> Binding.subModelSeq((fun m -> m.Details), (fun detail -> detail.id), fun () ->
[
"Id" |> Binding.oneWay (fun (_, detail) -> detail.id)
"Name" |> Binding.oneWay (fun (_, detail) -> detail.name)
"Content" |> Binding.oneWay (fun (_,detail) -> detail.content)
]) Suggestions? Thanks |
It's hard for this old dog to learn new tricks. Here is what I did:
Now what? How do I make a branch and share it? Thanks. I really would like to get this tab control working... Thanks. |
That's ok. Elmish.WPF is also a new trick for you, and we will help you learn both Elmish.WPF and GitHub. I think the correct order is to first learn GitHub. Then it will be easier to learn Elmish.WPF. Do you program professionally? Have you used git? |
Following these instructions to
|
@bender2k14 I made a first attempt at a pull request on this issue. Not sure If I did all that was needed. Please advise. Thanks. |
@bender2k14 Actually, their both related issues. I am trying to make this simple wpf xaml to work correctly:
The TabItem Name becomes correctly resolved when the Bindings use subModelSeq: "Details" |> Binding.subModelSeq((fun m -> m.Details), (fun detail -> detail.id), fun () -> However, doing so generates a dynamic viewmodel that feeds WPF an xType of: On the other hand, the x:Type correctly resolves when Hence, #273 and #268 are related (to me). Bottom line, I'm trying to get the above simple wpf xaml to work. Thanks. |
Can you change the code in your branch so that it can be immediately executed? |
@bender2k14 For old dogs like me, GitHub poses more of a challenge then you might think, but I it appears that I was successful with the pull request. How do you make an "Immediately Executed" code? (I will try). In the meantime, I hope my last comment explained my problem. Thanks. |
Creating a pull request was unnecessary, which is why I closed it. All you needed to do was share a link to your branch, which the PR did accomplish. Instead of using GitHub, can you share a link to a ZIP of your code?
Whether via a ZIP file or GitHub, I would like you to organize your code so that I can open a solution file, set some project as the startup project, and run your code from within Visual Studio. In contrast, I don't want to copy paste your code from multiple code blocks in comments on GitHub and figure out myself how they should be related to each other.
I generally understand your problem, but I am concerned that you would be able to understand answers given to at the same level of disorganized detail that characterize your questions. I think the best way to help you is to first help you ask better questions, especially by being able to effectively share the code that you are having trouble with. After we have a more specific question, we will be able to give you a precise answer in return. |
@bender2k14 Try Try Again. I appreciate your patience. I've attempted to do what you ask, although honestly, I do not know how you can use the result. Try: https://github.com/awaynemd/TabControlDemo3.git. This "should" consist of two projects: TabControlDemo3 is supposed to be the startup project (its not obvious to me that this came through the solution transfer). If this project is run, what you should see is a nice TabConrol with Headers on each of the tab items. However, clicking on any of the tabitems will show that WPF is unable to find the Object returned by Elmish.WPF. How'd I do? |
Getting closer! There is no solution ( I sent you an email to provide more assistance. |
@bender2k14 I've been playing around with this...but nothing I can do seems to let me upload two project files to the same GitHub repository...What's the trick? (When you say "its own folder", do you mean physical OS file folder, or do you mean separate VS Solution folders?).. Thanks. |
git and GitHub certainly support folders. The root of this repo contains the folders
Look at this repository that I recently created in GitHub. It mostly contains the files and folder that Visual Studio creates when creating a WPF project and a solution to contain it. Specifically, it has a folder named |
@bender2k14 Thanks....but How did you create and upload the folders? Pushing from Visual Studio only seems to allow me the one directory holding the solution and no subdirectories...so the references to projects outside of the top directory fail :( That is, I need multiple projects in same repo...I know it is supported, but I have no idea how to do it. Thanks. |
I know other people that interact with git through Visual Studio, but I almost never do. Instead, try interacting with git via the command line or a GUI like Sourcetree. |
@awaynemd your
[<RequireQualifiedAccess>]
type DetailType =
| ContactDetail
| Internet
| PhoneNumber
| Address
type Detail = { Id: Guid; Name: string; Content: string; Text: string ; Type: DetailType } and to have View that depends on DetailType you can use DataTemplateSelector |
@awaynemd If you want to keep your model types as is then you can use IValueConverter. This converter should return the list of real VM types, i.e.: type GetDetailsVMToResource() =
let toVM =
function
| Details.Address(a,_) -> a |> box
| Details.Internet(i, _) -> i |> box
| Details.PhoneNumber(p, _) -> p |> box
| Details.ContactDetail(c, _) -> c |> box
interface IValueConverter with
member this.Convert(value: obj, targetType: System.Type, parameter: obj, culture: System.Globalization.CultureInfo): obj =
match value with
| :? list<Details> as details ->
details
|> List.map toVM
|> box
| _ -> failwith "shouldn't happen"
member this.ConvertBack(value: obj, targetType: System.Type, parameter: obj, culture: System.Globalization.CultureInfo): obj =
raise (System.NotImplementedException()) With binding from VM side: "Details" |> Binding.oneWay(fun m -> m.Details) and in the xaml somewhere where you keep resources <conv:GetDetailsVMToResource x:Key="toDVMc" /> binding: <TabControl Grid.Row="1" ItemsSource="{Binding Details, Converter={StaticResource toDVMc}}"> |
@FoggyFinder I really like the idea of the DataTemplateSelector...but am having a hard time making it work. The Tab Item Headers are correctly typed, but I have no idea how to write the DataTemplateSelector (in C#??)
The 'item' here is something along the lines of 'ViewModel'2<object,object>' and I can tell no difference between which tab item is selected ????? :(o Here is what I have so far:
And for the C# XAML:
Thank you for your help! |
@awaynemd almost there! F# part:
type ContactDetail = { Name: string; Content: string; Text: string }
type Internet = { Name: string; Content: string; Text: string }
type PhoneNumber = { Name: string; Content: string; Text: string }
type Address = { Name: string; Content: string; Text: string }
"Details" |> Binding.subModelSeq( (fun m -> m.Details), (fun e -> e.Id),
(fun () -> [
"Name" |> Binding.oneWay (fun (_, e) -> e.Name)
"Content" |> Binding.oneWay (fun (_, e) -> e.Content)
])) with "Details" |> Binding.oneWay (fun m -> m.Details)
let init () =
{ Details = [{Id=0; Name="Contact Detail"; Content="Content for Contact Detail"; Text= "Text for Contact Detail"; Type=DetailType.ContactDetail}
{Id=1; Name="Internet"; Content="Content for Contact Detail"; Text= "Text for Internet"; Type=DetailType.Internet}
{Id=2; Name="Phone Number"; Content="Content for Contact Detail"; Text= "Text for Phone Number"; Type=DetailType.PhoneNumber}
{Id=3; Name="Address"; Content="Content for Contact Detail"; Text= "Text for Address"; Type=DetailType.Address}
]
Selected = Some 3 } Content is the same for all items. Probably let init () =
{ Details = [{Id=0; Name="Contact Detail"; Content="Content for Contact Detail"; Text= "Text for Contact Detail"; Type=DetailType.ContactDetail}
{Id=1; Name="Internet"; Content="Content for Internet Detail"; Text= "Text for Internet"; Type=DetailType.Internet}
{Id=2; Name="Phone Number"; Content="Content for Phone Detail"; Text= "Text for Phone Number"; Type=DetailType.PhoneNumber}
{Id=3; Name="Address"; Content="Content for Address Detail"; Text= "Text for Address"; Type=DetailType.Address}
]
Selected = Some 3 } C# part:
XAML: <DataTemplate x:Key="ContactDetailTemplate">
<local:ContactDetailView />
</DataTemplate>
<DataTemplate x:Key="InternetTemplate">
<local:InternetView />
</DataTemplate>
<DataTemplate x:Key="PhoneNumberTemplate">
<local:PhoneNumberView />
</DataTemplate>
<DataTemplate x:Key="AddressTemplate">
<local:AddressView />
</DataTemplate> Selector: public class PropertyDataTemplateSelector : DataTemplateSelector
{
public DataTemplate ContactDetailTemplate { get; set; }
public DataTemplate AddressTemplate { get; set; }
public DataTemplate PhoneNumberTemplate { get; set; }
public DataTemplate InternetTemplate { get; set; }
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
if (item is Models.FrontOffice.Detail detail)
{
var dType = detail.Type;
if (dType.IsAddress)
{
return AddressTemplate;
}
if (dType.IsContactDetail)
{
return ContactDetailTemplate;
}
if (dType.IsPhoneNumber)
{
return PhoneNumberTemplate;
}
if (dType.IsInternet)
{
return InternetTemplate;
}
throw new NotImplementedException("Not implemented yet");
}
return null;
}
} Result: If something goes wrong I can open PR to your repo |
@FoggyFinder OMG! It works! I tried for two weeks to figure this out and got nowhere. I can't thank you enough! It will take me another two weeks to completely understand it--there is much to learn here. BTW, how did you get a movie of the result and upload it to this site? Honors to you sir, thanks for the help. For any newbie, this is a good example of all (or most) of the mistakes a newbie can make and the great help the people here can be. (Learning github, learning F#, learning "repositories", learning elmish.wpf--this "issue" covered much. To all those in power, it would be a good learning example for other newbies like myself). |
You're welcome. Feel free to ask any Qs. There are a lot of resources that can speed up learning curve. For WPF-related things there is SO chat room I got help there many times. Wonderful place but the chat is mostly inactive on weekend. For F#: "Central" place is F# Slack Also there is a community forum F# Forum. Not very active now but I hope it changes one day. There is also room among SO-chats: F# room And two really new but perspective Q&A sites CoDidact and TopAnswers. I didn't mention F# sub-reddit and other popular places like SO because I don't check them. But I'm sure you can get help there as well.
I use ScreenToGif For the second part: File attachments on issues and pull requests I hope Elmish.WPF maintainers don't mind that my comment contains so many references =) |
@FoggyFinder Much thanks. Now to figure out how a tab item can itself contain another tab control ( My app has multiple layers). Bye (for now). |
Absolutely not! Just the opposite. I am very grateful for all the help you have given @awaynemd. Thank you very much :) |
(I'm a newbie here and haven't got the hang of making a branch as yet :))
I am trying to make this WPF XAML work. The problem is Elmish.WPF is returning
Elmish.WPF.ViewModel'2[System.Object.System.Object]
and not one of the expected types of ContactDetail, Internet, etc..so the DataTemplate fails to branch.
How do I fix this?
Thank you for any help.
Here is the supporting F# file using Elmish.WPF
The text was updated successfully, but these errors were encountered: