Jump between view and view model - visual-studio-2010

Is there a way to make Resharper or "just" Visual Studio (perhaps using a macro) jump between the view and the it's view model in the MVVM pattern.
Like Resharper can jump between the xaml and it's codebehind using F7 and Shift-F7
I follow the convention that the files are located like this
\Views\name\AbcView.xaml
\ViewModels\name\AbcViewModel.xaml

Perhaps I should have googled first, here is a macro to do the same thing for .cpp and. .h files
I changed it a bit and assigned the macro to Ctrl+F7. Seems to work fine
Public Sub SwitchBetweenViewAndViewModel()
'=====================================================================
' If the currently open document is a view or viewmodel, attempts to
' switch between them
'=====================================================================
Dim currentDocument As String
Dim targetDocument As String
currentDocument = ActiveDocument.FullName
If currentDocument.ToLower().Contains("\views\") And _
(currentDocument.EndsWith("View.xaml", StringComparison.InvariantCultureIgnoreCase) Or _
currentDocument.EndsWith("View.xaml.cs", StringComparison.InvariantCultureIgnoreCase)) Then
targetDocument = currentDocument
targetDocument = targetDocument.Replace(".xaml.cs", "")
targetDocument = targetDocument.Replace(".xaml", "")
targetDocument = targetDocument.Replace("\Views\", "\ViewModels\")
targetDocument = targetDocument + "Model.cs"
ElseIf currentDocument.ToLower().Contains("\viewmodels\") And currentDocument.EndsWith(".cs", StringComparison.InvariantCultureIgnoreCase) Then
targetDocument = currentDocument
targetDocument = targetDocument.Replace("\ViewModels\", "\Views\")
targetDocument = targetDocument.Replace("ViewModel.cs", "View.xaml")
End If
If System.IO.File.Exists(targetDocument) Then
OpenDocument(targetDocument)
End If
End Sub
'=====================================================================
' Given a document name, attempts to activate it if it is already open,
' otherwise attempts to open it.
'=====================================================================
Private Sub OpenDocument(ByRef documentName As String)
Dim document As EnvDTE.Document
Dim activatedTarget As Boolean
activatedTarget = False
For Each document In Application.Documents
If document.FullName = documentName And document.Windows.Count > 0 Then
document.Activate()
activatedTarget = True
Exit For
End If
Next
If Not activatedTarget Then
Application.Documents.Open(documentName, "Text")
End If
End Sub

What if more than one ViewModels are releated to the same View? :)
U may simply use DesignInstance markup extension to get R# navigation and code completion in binding work well:
namespace WpfApplication1.ViewModels
{
public class PersonViewModel
{
public string Name { get; set; }
public int Age { get; set; }
}
}
And the corresponding view:
<Window x:Class="WpfApplication1.Views.PersonView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="PersonInfo" Height="300" Width="300"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
xmlns:vms="clr-namespace:WpfApplication1.ViewModels"
d:DataContext="{d:DesignInstance Type=vms:PersonViewModel}">
<UniformGrid>
<TextBlock Grid.Row="0" Grid.Column="0" Text="Name" />
<TextBlock Grid.Row="0" Grid.Column="1" Text="Age" />
<TextBlock Grid.Row="1" Grid.Column="0" Text="{Binding Name}" />
<TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding Age}" />
</UniformGrid>
</Window>
Now R# can verify all the references to ViewModel properties in bindings, help you to complete property names and also can navigate directly to this properties. Moreover, all the code above is quickly baked using the R# Specify DataContext type in ... quick fix (at unresolved binding expressions).
p.s. View still have no dependency on ViewModel because all design-time attributes will be removed after compilation (by mc:Ignorable="d" attribute).

Using #Karstens answer I changed the sub that switches in between files to both being able to switch in between .cpp and .h files, as well as View and View Model files.
If you want to do the same, follow the instructions in his link but use this sub instead:
'=====================================================================
' If the currently open document is a CPP or an H file, attempts to
' switch between the CPP and the H file.
'
' If the currently open document is a View.xml or an ViewModel.cs file, attempts to
' switch between the View and the ViewModel file.
'=====================================================================
Sub SwitchBetweenAssociatedFiles()
Dim currentDocument As String
Dim targetDocument As String
currentDocument = ActiveDocument.FullName
If currentDocument.EndsWith(".cpp", StringComparison.InvariantCultureIgnoreCase) Then
targetDocument = Left(currentDocument, Len(currentDocument) - 3) + "h"
ElseIf currentDocument.EndsWith(".h", StringComparison.InvariantCultureIgnoreCase) Then
targetDocument = Left(currentDocument, Len(currentDocument) - 1) + "cpp"
ElseIf currentDocument.EndsWith("View.xaml", StringComparison.InvariantCultureIgnoreCase) Then
targetDocument = currentDocument.Replace("\Views\", "\ViewModels\")
targetDocument = targetDocument.Replace("\View\", "\ViewModel\")
targetDocument = targetDocument.Replace("View.xaml", "ViewModel.cs")
ElseIf currentDocument.EndsWith("ViewModel.cs", StringComparison.InvariantCultureIgnoreCase) Then
targetDocument = currentDocument.Replace("\ViewModels\", "\Views\")
targetDocument = targetDocument.Replace("\ViewModel\", "\View\")
targetDocument = targetDocument.Replace("ViewModel.cs", "View.xaml")
End If
If System.IO.File.Exists(targetDocument) Then
OpenDocument(targetDocument)
End If
End Sub
I assigned it to Alt + ยง which was free in my configuration. Handy next to Alt + Tab. ^_^

Related

What is the property in control to be set to get the value from AppResult.Text in Xamarin.UITest?

I am trying to create custom control in Xamarin.Forms which has the unique id for automation. So, i have set the android renderer's contentDescription property. So, i can get the AppResult.Label property to identify the control. But, my requirements is that how to get the control's text property? What property i have to set in control level with the corresponding text to get it in AppResult.Text property.
[Test]
[Description("SampleTest")]
public void WelcomeTextIsDisplayed()
{
App.Repl();
AppResult[] results = App.WaitForElement("myControl");
Assert.IsTrue(results[0].Text == "My Control Text", results[0].Text + "\n" + results[0].Description + "\n" + results[0].Id + "\n" + results[0].Label);
}
For more information, I have prepared the simple example to explain better about my case. Here, i have derived my custom control from Grid and i introduced the Text property. When i try to view the element using Repl() method, it does not show the Text property but it shows the text properties for Label & Entry controls.
<StackLayout >
<Label Text="Hello, Custom Renderer!" />
<local:MyEntry Text="In Shared Code" AutomationId="myEntry" />
<local1:CustomView Text="Sample" BackgroundColor="Red" HeightRequest="500" AutomationId="customControl" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand"/>
</StackLayout>
public class CustomView : Grid
{
public CustomView()
{
}
public static readonly BindableProperty TextProperty = BindableProperty.Create("Text", typeof(string), typeof(string),string.Empty);
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
Result while calling App.Repl() ,
I'm not sure how different Xamarin.Forms are to Xamarin.Android (which is mostly what my experience is in.)
What happens if you try
app.Query(c => c.Id("NoResourceEntry-2").Property("Text")).SingleOrDefault();
or some variation of the above? Can you then do something with this? I Hope this helps or points you in the right direction.
Try to use with index position like this:
app.Query(c=>c.Id("NoResourceEntry-2"))[0].Text
similarly you can use class for same:
app.Query(c=>c.Class("LabelRenderer"))[0].Text
Query for Class("LabelRenderer") gave 2 results. So in above example, you can see it gave you 2 results but you have to use index for particular result.

How can I bind the value of a field to a label in Xamarin?

Here is what I tried. Note that I removed parts of the XAML to make the question shorter but I tested it out by setting detailx.text in my cs and when I do it that way it displays XXXX:
<Frame x:Class="Japanese.PhrasesFrame">
<StackLayout x:Name="phrasesFrameStackLayout" >
<Grid x:Name="phraseGrid">
<Grid x:Name="wordGrid" >
<Grid x:Name="detailGrid">
<Label x:Name="detail1" Text="{Binding English}" XAlign="Center" />
<Label x:Name="detailx" XAlign="Center" />
In my CS I have
public PhrasesFrame()
{
InitializeComponent();
correctButton.Clicked += correctButtonClicked;
resetButton.Clicked += resetButtonClicked;
SetBindings();
wordGrid.BindingContext = AS.phrase;
}
In a method I have this:
public partial class PhrasesFrame : Frame
{
Random rand = new Random();
public PhrasesFrame()
{
InitializeComponent();
wordGrid.BindingContext = AS.phrase;
AS.phrase = new PSCViewModel() { English = "abcd" };
this.detailx.Text = "XXXX";
}
My problem is that when I used Binding English then the label never shows the text abcd but I do see the XXXX
Can someone tell me if I am missing something obvious. I tried everything but no success.
Try changing the order, like this:
AS.phrase = new PSCViewModel() { English = "abcd" };
wordGrid.BindingContext = AS.phrase;
Whenever you set the BindingContext at that moment it is applied, as is. If you make changes afterwards, you can, but you need to implement the INotifyPropertyChanged event to fire off a signal to the UI indicating which property has changed. Only then will it be update in the UI.

pass data from viewmodel to code behind windows phone

I was trying to use the MVVM pattern on my first (very simple) WP7 app but I got seriously stuck and now I am just trying to get it working without caring about MVVM.
I have a MainViewModel for my MainPage, which works fine. I have a button that passes some data and navigates to a "details page." I had setup a navigation service to navigate to the details page and pass parameters, which works fine. I just couldn't get the databinding to the view working. Since it is a simple app, I decided I would pass the data from the DetailsPageVieModel.cs to the DetailsPage.xaml.cs code behind and do the work there. Here is what that veiw model portion looks like.
public override void Initialize(IDictionary<string, string> parameters)
{
DetailsPage dp = new DetailsPage();
//DetailsPage dp = Application.Current.RootVisual as DetailsPage;
base.Initialize(parameters);
parameters.TryGetValue("url", out vidUrl);
dp.LoadVideoData(vidUrl);
}
In my DetailsPage.xaml.cs I have the following:
public void LoadVideoData(string url)
{
HtmlWeb doc = new HtmlWeb();
doc.LoadAsync("http://mydomain.com/video.php?url=" + url);
doc.LoadCompleted += doc_LoadCompleted;
}
private void doc_LoadCompleted(object sender, HtmlDocumentLoadCompleted e)
{
this.vidTitle.Text = e.Document.GetElementbyId("title").InnerText;
vidId = e.Document.GetElementbyId("youtubeId").InnerText;
this.vidUrl.Source = new Uri("http://mydomain.com/video.php?url=" + vidUrl, UriKind.Absolute);
BitmapImage bi = new BitmapImage();
using (IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream fileStream = myIsolatedStorage.OpenFile("temp.jpg", FileMode.Open, FileAccess.Read))
{
bi.SetSource(fileStream);
this.vidImg.Height = bi.PixelHeight;
this.vidImg.Width = bi.PixelWidth;
}
}
this.vidImg.Source = bi;
}
And here is the relevant DetailsPage.xaml code
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<StackPanel>
<TextBlock x:Name="vidTitle" Canvas.ZIndex="99" />
<TextBlock Canvas.ZIndex="99" Text="Tap on the image to view the video." FontSize="14" Margin="0"/>
<Button Margin="0 -50" Padding="0" BorderThickness="0">
<Image x:Name="vidImg" Height="225" />
</Button>
<StackPanel Canvas.ZIndex="99" Height="516">
<phone:WebBrowser x:Name="vidUrl" IsScriptEnabled="True" Height="516" Margin="0"/>
</StackPanel>
</StackPanel>
</Grid>
I am guessing the problem lies with the following
DetailsPage dp = new DetailsPage();
//DetailsPage dp = Application.Current.RootVisual as DetailsPage;
Neither of these lines of code works. The first line executes properly but the page doesn't get updated with the proper data. And the second line gives me a runtime error message when it gets to the dp.LoadVideoData(vidUrl); line.
This is my first Windows Phone app and I would appreciate any help anyone can provide.
Kamal
After digging around some more, I found the following solution.
DetailsPage currentPage = (App.Current as App).RootFrame.Content as DetailsPage;
I put this code in DetailsPageViewModel.cs. But for other newbies like me, there is nothing special about the name of the file. It could have very well been Monkey.cs. The above code just gives you access to the code behind of the current page being displayed.

Visibility (Windows Phone 7)

Sorry if I ask a basic question !
Class Customer has got string Name and int Age
In MainPage.xaml.cs I have :
ObervableCollection < Customer > Customers
In MainPage.xaml :
<Listbox x:Name = "ListCustomer"
ItemsSources = "{Binding Customers}"/>
<Button x:Name = "Button1" Visibility = "Collapsed"/>
How can i set Button1 visibility in MainPage.xaml.cs?
if(ListCustomer == null) <-- doesn't have data Button1 is collapsed, if Listbox (or Customer - I don't know)
has got data Button1 is visibled
//or if(Customers == null)
{
Button1.visibility = visibility.visibled
}
Where i can put it ?
(in Navigation To, Navigation From, or Page_Load, some where...)
Button1.Visibility = System.Windows.Visibility.Collapsed;
or
Button1.Visibility = System.Windows.Visibility.Visible;
The above code should help you make the button invisible and visible respectively.
It would be best if you could put it in the Loaded event handler. This is where you can be sure that all the UI elements are loaded.

Windows Phone 7 Back button and application Tombstone?

In my application i had done this to map my uri in app.xaml.cs, now the thing is if my application deactivates my application exits on MainPage.xaml rather than Eula.xaml. Else the app exits on the same page on which it starts.
In App.xaml
<UriMapper:UriMapper x:Name="mapper">
<UriMapper:UriMapping Uri="/MainPageOrEULA.xaml"/>
</UriMapper:UriMapper>
and in App.xaml.cs
// Get the UriMapper from the app.xaml resources, and assign it to the root frame
UriMapper mapper = Resources["mapper"] as UriMapper;
RootFrame.UriMapper = mapper;
// Update the mapper as appropriate
IsolatedStorageFile isoStorage = IsolatedStorageFile.GetUserStoreForApplication();
if (isoStorage.FileExists("DataBase/MyPhoneNumber.txt"))
{
mapper.UriMappings[0].MappedUri = new Uri("/MainPage.xaml", UriKind.Relative);
}
else
{
mapper.UriMappings[0].MappedUri = new Uri("/EULA.xaml", UriKind.Relative);
}
Please guide me for the same.
Regards,
Panache.
I suggest that rather than having a whole separate page (which interrupts navigation as you've noticed), just put a grid or usercontrol containing the EULA on the front page that isn't visible. When the user first opens the page, you show the grid/usercontrol, but on subsequent runs, you don't.
<Grid x:Name="LayoutRoot">
<Grid Name="EULA" Visibility="Collapsed" >
<TextBlock Text = "You agree ...." />
<Button Grid.Row="1" Content="I Agree" Click="AgreeClick" />
</Grid>
<Grid Name="MainGrid" >
....
Then in your code behind you can add your test to the loaded event
private void MainPageLoaded()
{
IsolatedStorageFile isoStorage = IsolatedStorageFile.GetUserStoreForApplication();
if (!isoStorage.FileExists("DataBase/MyPhoneNumber.txt"))
{
EULA.Visibility = Visibility.Visible;
MainGrid.Visibility = Visibility.Collapsed;
}
}
Then when the "I agree" button is clicked you can store the file and show the main grid
private void AgreeClick(....)
{
// Create isolated storage file
....
// Hide eula control
EULA.Visibility = Visibility.Collapsed;
MainGrid.Visibility = Visibility.Visible;
}

Resources