|
SledgeHammer01 wrote: 1) what's the difference between the PC version and the tablet version?
The Tablet exposes only pieces of the PC version. The look of those parts is also different. So that's why I have the Shared project - to hold the ViewModels that are common to both.
SledgeHammer01 wrote: 2) why are you assigning VMs from code? ViewLocator is your friend.
Because I don't know better
SledgeHammer01 wrote: There is no need to have two separate VMs.
I don't have separate VM's. Again, the shared project holds the VM.
When you say ViewLocator, do you mean this?[^]
If it's not broken, fix it until it is
|
|
|
|
|
Yup. That's ViewLocator. ViewLocator and DI are important to know. Really cleans up the code.
|
|
|
|
|
Ok, maybe I'm just not seeing it, but I can't find a decent example of this. All the examples I'm finding don't really seem to apply to what I'm doing.
Again, here's the problem I'm trying to solve...
The PC version looks like this[^]
Each 'Center' is essentially more or less the same - a list and tab control which can have any number of the view open. In the image, the Job Center is open with one Job open. The area in red is the JobView. The code in the JobCenter's LoadViiew (see below) method creates an instance of the JobViewModel and JobView, assigned the VM to the View's DataContext, assigns the view to the tab's Content property, and add the tab.
The Tablet's Home[^] is different. It's Job View[^] is much smaller and has less elements.
Here's where my confusion/problem lies...
Both Job views can use the same VM, so the VM is in the shared project.
Both Job views need to open dialogs. For example the Address Editor. In the PC version this is a model dialog. In the Tablet version is will be another 'flat' view that replaces the current view. The user will add or select an address, click Ok, the view goes away and the Job view comes back.
1) What's the right way to load the Address Editor?
2) The Center's all load their child views onto tabs like this:
private void loadView(JobArgs Args)
{
ViewInfo tabInfo = new ViewInfo
{
View = View.Job,
EntityId = Args.Job.JobRevisionId
};
if (tabInfo.EntityId > 0 && TabManager.IsTabOpen(tabInfo))
{
TabManager.ActivateTab(tabInfo);
}
else
{
JobViewModel vm = new JobViewModel();
vm.Load(Args);
UserControl view = new JobView();
view.DataContext = vm;
TabItem tabItem = new TabItem
{
Header = vm.GetEntityCaption(),
Content = view,
Tag = tabInfo
};
TabManager.AddTab(tabItem, true);
}
}
The obvious problem here is that the ViewModel knows about the View.
So how do I have the VM load the right view? regardless of which version I'm in. I'm confused because the VM lives in the Shared project, and the target views are in their own project. We discussed the ViewModelLocator, but I cannot find an example that seems like it works in this scenerio.
I'm guessing the ViewModelLocator's job is to say, "Hey I'm view 'JobView' and I need a view model, so go get it for me"?
While I like the idea, how and where do I handle opening dialogs, if not in the Job's VM?
I'm pretty confused about the right way to open/work with child views.
Let me ask the question this way, so I'm clear...
In the PC version, when the New button is clicked in the JobCenter, I need to add a tab and put a JobView control on a it. I have been doing all of this in the VM, but it's wrong. What is the right way to do this? An example would be great, if you know of one.
Thanks
If it's not broken, fix it until it is
|
|
|
|
|
If I do a tabbed view, it really depends on if the tabs are hard coded or dynamic.
If its hard coded, I hard code it in the XAML (psuedo code):
<TabControl>
<Tabs>
<Tab>
<ChildView1 />
</Tab>
<Tab>
<ChildView2 />
</Tab>
<Tabs>
</TabControl>
The XAML for ChildView1 and ChildView2 would use the ViewLocator to find the VM. Something like:
<UserControl somenamespace:ViewModelBase.ViewModel="{x:Type local:DocumentMapCtrlVM}" ... />
your ViewLocator should wire up the DataContext, etc. as shown in that link.
If its dynamic (or determined at runtime), you'd need to build a collection of some object where you have the name of the tab and the usercontrol instance for example and then bind the tab content to the object.UserControl from the collection with a data template.
For opening a dialog, I like to use a dialog service. That kind of needs a DI engine / container. You'd register a generic base interface:
interface IDialogService
{
AddressObject ShowAddressDialog(Window owner);
}
for example... in the tablet version, you'd register a version that slides it in like you are doing now and in the desktop version, you'd register a version that shows a popup dialog version instead, but its all the same interfaces, so your calling code is the same for both versions.
The end result of putting ViewLocator, DI and services together is that it solves all your problems lol... but you are really covering a LOT of ground with those 3 items and its not really something I can explain in 5 sentences lol..
|
|
|
|
|
Wow, well maybe I'm not too far off then. Consider...
SledgeHammer01 wrote: If its hard coded, I hard code it in the XAML (psuedo
code): <TabControl>
<Tabs> <Tab>
<ChildView1 />
</Tab> <Tab>
<ChildView2 />
</Tab>
<Tabs> </TabControl> The XAML for ChildView1 and
ChildView2 would use the ViewLocator to find the VM. Something
like: <UserControl
somenamespace:ViewModelBase.ViewModel="{x:Type local:DocumentMapCtrlVM}" ...
/> your ViewLocator should wire up the DataContext, etc. as
shown in that link. If its dynamic (or determined at runtime),
you'd need to build a collection of some object where you have the name of the
tab and the usercontrol instance for example and then bind the tab content to
the object.UserControl from the collection with a data template.
1) I already do all this
SledgeHammer01 wrote: For opening a dialog, I like to use a dialog service. That kind of needs a DI
engine / container. You'd register a generic base
interface: interface IDialogService {
AddressObject ShowAddressDialog(Window owner); } for example...
in the tablet version, you'd register a version that slides it in like you are
doing now and in the desktop version, you'd register a version that shows a
popup dialog version instead, but its all the same interfaces, so your calling
code is the same for both versions.
2) I'm already doing this.
But think of this... I think my problem is that I don't need a ViewModelLocator - I need a ViewLocator...
Since both the PC or Tablet JobViews are using the same VM, the only questions is which View to load.
What do you think?
If it's not broken, fix it until it is
|
|
|
|
|
At some point you're going to have to make a true / false decision in your code for tablet vs. PC. I have a UI library that styles differently in XP vs. Windows 7 for example. I have a single, global static DP and I select the proper template in XAML via a data trigger based on that DP. You can do something similiar. Apply the PC view by default and switch it out for the tablet view via a data trigger if the global IsTablet DP is set.
|
|
|
|
|
<blockquote class="FQ"><div class="FQA">Kevin Marois wrote:</div>Let me ask the question this way, so I'm clear...<BR> <BR>In the PC
version, when the New button is clicked in the JobCenter, I need to add a tab
and put a JobView control on a it. I have been doing all of this in the VM, but
it's wrong. What is the right way to do this? An example would be great, if you
know of one.<BR></blockquote>
I forgot to address this part in my original response.
Basically, your New button would send a command to the VM and the VM would add an object to its "TabItemCollection" that the tab control is bound to. Stylized with the DataTemplate of course to bind the properties correctly.
So you might have something like:
class ViewInfo
{
string Title;
UserControl UserControl;
}
ObservableCollection<ViewInfo> Tabs;
the tab title would be bound to the ViewInfo.Title property. and the Tab content would be bound to the ViewInfo.UserControl property.
|
|
|
|
|
How to perform file transfer same like as it happen in teamviewer and ammyy before in wpf
i want to open a window in which on the left side i get complete directories of my own system and on the right side i get all the directories of remote system in wpf using c#
can anyone halp me in it, to give me just an idea only
i dont want to access any remote system using theri network username and password i jst want to access it through their ip addresses
someone please help me in it, to give me an idea on it
|
|
|
|
|
Arun kumar Gautam wrote: i dont want to access any remote system using theri network username and password i jst want to access it through their ip addresses Then you will need a client application (like an ftp server) on the remote system that will give you the directory details and manage the data transfers.
Veni, vidi, abiit domum
|
|
|
|
|
bt ftp also needs client system username and password
|
|
|
|
|
Then you need to write your own client agent that allows you to connect without it.
Also please use the correct forum in future, this is not a WPF/Silverlight issue.
Veni, vidi, abiit domum
|
|
|
|
|
Hi,
if you do use Socket Programming, there no need to credential of Remote server just use ip address.
mohit Saxena
|
|
|
|
|
thnks mohit i really appreciate ur help.
|
|
|
|
|
But remember, you will still need a program on the remote system that will listen for and accept socket connect requests.
Veni, vidi, abiit domum
|
|
|
|
|
Hi... So I'm creating a column collection for a data grid in the code behind because I don't know the number of columns needed until run time. I need to bind the background color to a converter but i'm not sure how to do it. The background property is typed as a Brush, but of course the converter is a binding... so how do I get this working? In the code below, the "DataMemberBinding" works because that property is a binding type... So I just need to get the background working.
Thanks,
Sam.
Dim c = New Telerik.Windows.Controls.GridViewDataColumn With {.Header = sched.ShipName,
.IsReadOnly = True,
.IsFilterable = True,
.IsSortable = True,
.Background = New System.Windows.Data.Binding With {.Converter = New BackgroundColorConverter(),
.ConverterParameter = (s + 1).ToString},
.IsGroupable = False,
.ShowFieldFilters = True,
.ShowDistinctFilters = False,
.DataMemberBinding = New System.Windows.Data.Binding With {.Converter = New ColumnConverter(),
.ConverterParameter = (s + 1).ToString}
}
columnCollection.Add(c)
|
|
|
|
|
Try something like this:
Dim column As New GridViewDataColumn With
{
.Header = sched.ShipName,
.IsReadOnly = True,
.IsFilterable = True,
.IsSortable = True,
.IsGroupable = False,
.ShowFieldFilters = True,
.ShowDistinctFilters = False,
.DataMemberBinding = New Binding With
{
.Converter = New ColumnConverter(),
.ConverterParameter = (s + 1).ToString
}
}
Dim backgroundBinding As New Binding With
{
.Converter = New BackgroundColorConverter(),
.ConverterParameter = (s + 1).ToString},
}
column.SetBinding(GridViewDataColumn.BackgroundProperty, backgroundBinding)
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Thanks for the reply. SetBinding doesn't exist on the GridViewDataColumn type though... I did figure it out, however:
Dim c = New Telerik.Windows.Controls.GridViewDataColumn With {.Header = sched.ShipName,
.IsReadOnly = True,
.IsFilterable = True,
.IsSortable = True,
.IsGroupable = False,
.ShowFieldFilters = True,
.ShowDistinctFilters = False,
.DataMemberBinding = New System.Windows.Data.Binding With {.Converter = New ColumnConverter(),
.ConverterParameter = (s + 1).ToString}
}
Dim backgroundBinding As New System.Windows.Data.Binding With {.Converter = New BackgroundColorConverter,
.ConverterParameter = (s + 1).ToString}
backgroundBinding.Source = c
System.Windows.Data.BindingOperations.SetBinding(c, Telerik.Windows.Controls.GridViewDataColumn.BackgroundProperty, backgroundBinding)
columnCollection.Add(c)
|
|
|
|
|
USAFHokie80 wrote: SetBinding doesn't exist on the GridViewDataColumn type
The BindingOperations.SetBinding method is an extension method. If you import the System.Windows.Data namespace, you'll be able to call it as c.SetBinding(...) .
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Hi,
You can use DataGrid_AutoGeneratedColumns() event and set the datagrid.ColumnHeaderStyle,
can set background color ,fore-color etc,with help ColumnHeaderStyle Property.
I hope that it is useful for you.
Thanks
Mohit Saxena
mohit Saxena
|
|
|
|
|
Hi.
I have 2 DatePicker control in WPF Windows (start date and end date).
Where User should be able to select start date and end date.
End date should be lass then and not equal to end date.
I want to give validation when user leave the end date(DatePicker control) at that time.
|
|
|
|
|
|
I have a SL/WPF application that populates a datagrid. The button contains this code:
MyDomainContext context = new MyDomainContext();
dataGrid1.ItemsSource = context.DBTables;
context.Load(context.GetTwoDataBasesQuery());
The DomainServices.cs contains:
public IQueryable<DBTable>GetTwoDataBases()
{
return this.ObjectContext.DBTables;
}
This code works fine but returns all columns in the context
I need to return only two columns so changed is as follows
public IQueryable<DBTable>GetTwoDataBases()
{
return GetDBTables().Select(m => new { m.col1, m.col2 });
}
But code has errors, does not accept the "return" .
how do I get col1 and col2?
Many thanX
|
|
|
|
|
Can any one help me to write style for 2 textbox which should take input like Latitude , Longitude. with validation
|
|
|
|
|
|
And which format will be used - degrees, minutes, seconds, ...?
|
|
|
|
|