Load resource dictionary in wpf add in application - resources

Hi i need to make multilingual WPF office add-in. I want to use resources files. i call in my ThisAddIn_Startup function my SetLanguageDictionary
public static void SetLanguageDictionary()
{
try
{
//Get the assembly information
System.Reflection.Assembly assemblyInfo = System.Reflection.Assembly.GetExecutingAssembly();
Uri uriCodeBase = new Uri(assemblyInfo.CodeBase);
string path = Path.GetDirectoryName(uriCodeBase.LocalPath.ToString());
ResourceDictionary dict = new ResourceDictionary();
switch (Thread.CurrentThread.CurrentCulture.ToString())
{
case "en-US":
dict.Source = new Uri(path + "\\Resources\\en-US.xaml",
UriKind.Absolute);
break;
case "fr-FR":
dict.Source = new Uri(path + "\\Resources\\fr-FR.xaml",
UriKind.Absolute);
break;
default:
dict.Source = new Uri(path + "\\Resources\\en-US.xaml",
UriKind.Absolute);
break;
}
Application.Current.Resources.MergedDictionaries.Add(dict);
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
}
}
my resources files are there
<ResourceDictionary
xmlns ="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib">
<system:String x:Key="Ready">Ready</system:String>
<system:String x:Key="login">Login</system:String>
<!-- All StringResources Goes Here -->
</ResourceDictionary>
when loading i have the error :
System invalid operation exception : operation error loadfrom resouceDictionary with URI:"file:///c:
thanks for your reply

I solve my problem. It s just because load of resourcesdictionary could only be done by code behind xaml page.

You need to insert in File App.xaml the direction of your files.. in my case for example:
<Application x:Class="VBControl.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:VBControl"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resources\StringResources.xaml"/>
<ResourceDictionary Source="Resources\StringResources.en-EN.xaml" />
<ResourceDictionary Source="Resources\StringResources.pt-BR.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>

Related

UWP virtual keyboard pushes content up

I have an UWP app where my robots face gets pushed up when the virtual keyboard opens. Is it possible to have the scrollviewer stay in place and have the textbox stay in view when the virtual keyboard opens.
I see you can subscribe to the opening and hiding events but that does not give me any options on which ui elements can stay or hide. https://learn.microsoft.com/en-us/windows/uwp/input-and-devices/respond-to-the-presence-of-the-touch-keyboard
<Page
x:Class="VirtualKeyboardFix.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:VirtualKeyboardFix"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<ScrollViewer >
<Image Source="image.png" />
</ScrollViewer>
<TextBox HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="10" />
</Grid>
</Page>
Yes that is the answer Justin XL. Thanks a lot. If you want to post it as a reply instead of a comment then I will mark it as the answer.
Just in case anyone has the same problem.
namespace VirtualKeyboardFix
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
InputPane.GetForCurrentView().Showing += MainPage_Showing;
InputPane.GetForCurrentView().Hiding += MainPage_Hiding;
}
private void MainPage_Showing(InputPane sender, InputPaneVisibilityEventArgs args)
{
args.EnsuredFocusedElementInView = false;
InputTextBox.Margin = new Thickness(10, 10, 10, args.OccludedRect.Height + 10);
}
private void MainPage_Hiding(InputPane sender, InputPaneVisibilityEventArgs args)
{
args.EnsuredFocusedElementInView = false;
InputTextBox.Margin = new Thickness(10, 10, 10, 10);
}
}
}

Downloading a document on android

I want to download documents from the links ive scraped on the web, i have a listview listener so when i press one of the item in the list it will return a url, ive set it up so getLink will be the link of the pdf file i want to download and set up filenametoo.
getLink = http://www.phivolcs.dost.gov.ph/images/Flyer-eq-and-eq-hazards.pdf
filename = Flyer-eq-and-eq-hazards.pdf
So i call this inside my listview listener and its suppose to download but its not working.
new DownloadFile().execute(getLink, filename);
I have errors like java.io.IOException: open failed: ENOENT (No such file or directory)
insideMain
private class DownloadFile extends AsyncTask<String, Void, Void>{
#Override
protected Void doInBackground(String... strings) {
String fileUrl = strings[0]; // -> getLink = http://www.phivolcs.dost.gov.ph/images/Flyer-eq-and-eq-hazards.pdf
String fileName = strings[1]; // -> Flyer-eq-and-eq-hazards.pdf
String extStorageDirectory = Environment.getDataDirectory().toString();
File folder = new File(extStorageDirectory, "testthreepdf");
folder.mkdir();
File pdfFile = new File(folder, fileName);
try{
pdfFile.createNewFile();
}catch (IOException e){
e.printStackTrace();
}
FileDownloader.downloadFile(fileUrl, pdfFile);
return null;
}
}
downloadFile
package com.example.boneyflesh.homepage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
public class FileDownloader {
private static final int MEGABYTE = 1024 * 1024;
public static void downloadFile(String fileUrl, File directory) {
try {
URL url = new URL(fileUrl);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.connect();
InputStream inputStream = urlConnection.getInputStream();
FileOutputStream fileOutputStream = new FileOutputStream(directory);
int totalSize = urlConnection.getContentLength();
byte[] buffer = new byte[MEGABYTE];
int bufferLength = 0;
while ((bufferLength = inputStream.read(buffer)) > 0) {
fileOutputStream.write(buffer, 0, bufferLength);
}
fileOutputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.boneyflesh.homepage">
<!--
The ACCESS_COARSE/FINE_LOCATION permissions are not required to use
Google Maps Android API v2, but you must specify either coarse or fine
location permissions for the 'MyLocation' functionality.
-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" ></uses-permission>
<uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme"
tools:ignore="AllowBackup">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!--
The API key for Google Maps-based APIs is defined as a string resource.
(See the file "res/values/google_maps_api.xml").
Note that the API key is linked to the encryption key used to sign the APK.
You need a different API key for each encryption key, including the release key that is used to
sign the APK for publishing.
You can define the keys for the debug and release targets in src/debug/ and src/release/.
-->
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="#string/google_maps_key" />
<activity
android:name=".MapsActivity"
android:label="#string/title_activity_maps" />
<!--
ATTENTION: This was auto-generated to add Google Play services to your project for
App Indexing. See https://g.co/AppIndexing/AndroidStudio for more information.
-->
<meta-data
android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
<activity android:name=".GeohazardResults" />
<activity android:name=".MineralResults" />
<activity android:name=".LandformResults" />
<activity android:name=".Downloads"></activity>
</application>
EDIT
I called useFileAsyncTask(); then i received an error FATAL EXCEPTION: AsyncTask #1
Constructor
protected void useFileAsyncTask() {
DownloadFile task = new DownloadFile(this);
task.execute();
}
Asynktask
private class DownloadFile extends AsyncTask<String, Void, Void>{
private Context myContextRef;
public DownloadFile(Context context) {
myContextRef = context;
}
#Override
protected Void doInBackground(String... strings) {
//String fileUrl = strings[0]; // -> http://maven.apache.org/maven-1.x/maven.pdf
//String fileName = strings[1]; // -> maven.pdf
String extStorageDirectory = myContextRef.getFilesDir().toString();
//String extStorageDirectory = Environment.getDataDirectory().toString();
File folder = new File(extStorageDirectory, "testthreepdf");
folder.mkdir();
File pdfFile = new File(folder, filename);
try{
pdfFile.createNewFile();
}catch (IOException e){
e.printStackTrace();
}
FileDownloader.downloadFile(getLink, pdfFile);
return null;
}
}
downloadFile remains the same.
Change the line
String extStorageDirectory = Environment.getDataDirectory().toString();
to
String extStorageDirectory = context.getFilesDir().toString();
where context is the Context that you will need to supply to the AsyncTask.
Environment.getDataDirectory() is the system-wide user data directory where you may not create files while ontext.getFilesDir() is the data directory for your app where you may create files.

What are the best practices to dynamically create views and add controls to view using MVVM pattern

Can anyone give out the best practices for playing around with controls at runtime such as creating a new view,adding views inside a view,adding controls to containers using MVVM pattern without breaking mvvm pattern??
I am using MVVMlight toolkit..
please help me out in this regard..
Thanks in advance......
This post discusses the strategies for creating views (dialogs) from your view models.
Edit:
From your comment I take it that you got an user interface that has an add and delete button. The add button should add an item (type ?) to a ItemsControl ... hope that's correct.
So, how would I do this, well I would create a view model that has an ObservableCollecion<ItemViewModel>. The ItemViewModle is the view mode that represents the item that should be added to the ItemsControl (so in your case the view model backing your "rangeView").
Then I would add two commands that handle the addition and deletion of items. Both commands just add/remove ItemViewModels from your collection.
To show the items in the view I would bind the ItemControl.ItemsSource property to the collection in your main view model (i.e. the one holding the ItemViewModel instances). The I would supply an ItemTemplate to render the items on the screen.
Ok, here is an example of what I think you are trying to do (at least conceptionally). Complete Source Code here. In the example I used a ListBox as it allows me easily to determine which item is selected, this depends on your szenario. Also note that you have complete freedom to customize the Template, the ItemPanelTemplate, and DataTemplate to fit your needs. You can even use this approacht to create PanoramaPages in WP7!
2nd edit: ItemsControl does not have a SelectedItem property. To get to it you have to use a control inheriting from Selector (e.g. a ListBox as I did) or you can use the Selector directly.
ItemViewModel:
public class ItemViewModel : ViewModelBase
{
#region [Name]
public const string NamePropertyName = "Name";
private string _name = null;
public string Name {
get {
return _name;
}
set {
if (_name == value) {
return;
}
var oldValue = _name;
_name = value;
RaisePropertyChanged(NamePropertyName);
}
}
#endregion
}
MainViewModel:
public class MainViewModel : ViewModelBase
{
public MainViewModel() {
if (IsInDesignMode) {
this.Items = new ObservableCollection<ItemViewModel>(Enumerable.Range(0, 10).Select((x, i) => new ItemViewModel() { Name = "Design Time Item " + i }));
} else {
// Code runs "for real"
}
}
#region [AddCommand]
private RelayCommand _addCommand;
public RelayCommand AddCommand {
get {
return _addCommand ?? (_addCommand = new RelayCommand(
() => {
this.Items.Add(new ItemViewModel() { Name = "New item - " + DateTime.Now });
}
));
}
}
#endregion
#region [DeleteCommand]
private RelayCommand _deleteCommand;
public RelayCommand DeleteCommand {
get {
return _deleteCommand ?? (_deleteCommand = new RelayCommand(
() => {
this.Items.Remove(this.SelectedItem);
},
() => { return this.SelectedItem != null; }
));
}
}
#endregion
#region [Items]
public const string ItemsPropertyName = "Items";
private ObservableCollection<ItemViewModel> _items = new ObservableCollection<ItemViewModel>();
public ObservableCollection<ItemViewModel> Items {
get {
return _items;
}
set {
if (_items == value) {
return;
}
var oldValue = _items;
_items = value;
RaisePropertyChanged(ItemsPropertyName);
}
}
#endregion
#region [SelectedItem]
public const string SelectedItemPropertyName = "SelectedItem";
private ItemViewModel _selectedItem = null;
public ItemViewModel SelectedItem {
get {
return _selectedItem;
}
set {
if (_selectedItem == value) {
return;
}
var oldValue = _selectedItem;
_selectedItem = value;
RaisePropertyChanged(SelectedItemPropertyName);
// important in SL to notify command that can execute has changed !
this.DeleteCommand.RaiseCanExecuteChanged();
}
}
#endregion
}
MainPage.xaml
<UserControl
x:Class="MvvmLight1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Height="300"
Width="300"
DataContext="{Binding Main, Source={StaticResource Locator}}"
>
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Skins/MainSkin.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Grid x:Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<ListBox Grid.Row="0" ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="Margin" Value="0"/>
<Setter Property="Padding" Value="0"/>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<!-- we are dealing with ItemViewModels now -->
<Border BorderThickness="0,0,0,1" BorderBrush="Gray" Padding="10,5">
<TextBlock Text="{Binding Name}"/>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Right">
<Button Margin="5,10" Content="Add" Command="{Binding AddCommand}" Width="70"/>
<Button Margin="5,10" Content="Delete" Command="{Binding DeleteCommand}" Width="70"/>
</StackPanel>
</Grid>
</UserControl>

Adding portlet instance during page reload in Liferay

I am trying to add a new IFrame portlet in liferay on click of a link. I have achieved it with some issues.
First I created a portlet using liferay sdk and customized the default view.jsp:
<portlet:renderURL var="pageDisp">
<portlet:param name="jspPage" value="/view.jsp" />
</portlet:renderURL>
Google <br />
Yahoo <br />
Daily Tech <br />
Wired <br />
Changed portlet.xml from
<portlet-class>com.liferay.util.bridges.mvc.MVCPortlet</portlet-class>
to
<portlet-class>test.LinksPortlet</portlet-class>
I have implemented the following code in LinksPortlet:
public void render(RenderRequest request, RenderResponse response) throws PortletException, java.io.IOException {
log("LinksPortlet:render");
try {
ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(com.liferay.portal.kernel.util.WebKeys.THEME_DISPLAY);
LayoutTypePortlet layoutTypePortlet = themeDisplay.getLayoutTypePortlet();
List<Portlet> portletList = layoutTypePortlet.getPortlets();
for(Portlet p : portletList) {
log(p.getPortletId());
log(p);
log(p.getDisplayName());
log(p.getInitParams());
}
String c = request.getParameter("clink");
log(c);
if(c != null && (c.equals("g") || c.equals("y") || c.equals("d") || c.equals("w"))) {
String portletId = layoutTypePortlet.addPortletId(Long.parseLong(request.getRemoteUser()), PortletKeys.IFRAME, "column-2", -1);
log("portletId: "+portletId);
long companyId = themeDisplay.getCompanyId();
long ownerId = PortletKeys.PREFS_OWNER_ID_DEFAULT;
int ownerType = PortletKeys.PREFS_OWNER_TYPE_LAYOUT;
Layout layout = themeDisplay.getLayout();
PortletPreferences prefs = PortletPreferencesLocalServiceUtil.getPreferences(companyId, ownerId, ownerType, layout.getPlid(), portletId);
Locale locale = new Locale("en", "US");
prefs.setValue("portlet-setup-use-custom-title", "true");
if(c.equals("g")) {
prefs.setValue("src","http://www.google.com");
prefs.setValue("portlet-setup-title-" + LocaleUtil.toLanguageId(locale), "Google");
}
else if(c.equals("y")) {
prefs.setValue("src","http://www.yahoo.com");
prefs.setValue("portlet-setup-title-" + LocaleUtil.toLanguageId(locale), "Yahoo");
}
else if(c.equals("d")) {
prefs.setValue("src", "http://www.dailytech.com");
prefs.setValue("portlet-setup-title-" + LocaleUtil.toLanguageId(locale), "Daily Tech");
}
else if(c.equals("w")) {
prefs.setValue("src", "http://www.wired.com");
prefs.setValue("portlet-setup-title-" + LocaleUtil.toLanguageId(locale), "Wired");
}
PortletPreferencesLocalServiceUtil.updatePreferences(ownerId, ownerType, layout.getPlid(), portletId, prefs);
portletList = layoutTypePortlet.getPortlets();
for(Portlet p : portletList) {
if(p.getPortletId().equals(portletId)) {
break;
}
}
LayoutLocalServiceUtil.updateLayout(layout.getGroupId(), layout.isPrivateLayout(), layout.getLayoutId(), layout.getTypeSettings());
}
}
catch(Exception e) {
log("LinksPortlet:doView:Exception");
e.printStackTrace();
}
super.render(request, response);
}
The issue with the above implementation is that the new portlet appears on the screen after the page reload:
http://www.go-ahead.in/books/1.JPG
http://www.go-ahead.in/books/2.JPG
http://www.go-ahead.in/books/3.JPG
The reason for the issue is that the new portlet is added after the layout render starts. Is it possible to customize or add a hook for performing the action I am performing during page / layout load. I came across the source LayoutAction.java of liferay where portlets are added. Is there any way to add a post hook to add the portlet without modifying the liferay's source code?
I am using Liferay 6.0.5.
Thanks in advance.
Found the solution to the problem.
I have moved the code from render method to processAction and creating the link using <portlet:actionURL> tag.

How to get the context item in Workflow activity (SharePoint)

I am writing custom activity for sharepoint workflow and I don't know how I can use current workflow item, SPWeb or SPSite.
I see http://blogs.microsoft.co.il/blogs/davidbi/archive/2008/07/21/How-to-get-the-context-item-in-workflow-activity-sharepoint.aspx but xml routines of this solution is too bad for me.
Perhaps there is another code-only solution to get context item in Workflow activity?
The answer to this is a couple steps:
Add the properties to your Custom Activity .cs
Link the properties in your .actions file (so SPD knows how to map to your properties)
Use the properties in your code
STEP 1: Here is the code for the properties (my class is named GetEmails which you will need to rename to be your class):
public static DependencyProperty __ContextProperty = System.Workflow.ComponentModel.DependencyProperty.Register("__Context", typeof(WorkflowContext), typeof(GetEmails));
[Description("The site context")]
[Category("User")]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public WorkflowContext __Context
{
get
{
return ((WorkflowContext)(base.GetValue(GetEmails.__ContextProperty)));
}
set
{
base.SetValue(GetEmails.__ContextProperty, value);
}
}
public static DependencyProperty __ListIdProperty = System.Workflow.ComponentModel.DependencyProperty.Register("__ListId", typeof(string), typeof(GetEmails));
[ValidationOption(ValidationOption.Required)]
public string __ListId
{
get
{
return ((string)(base.GetValue(GetEmails.__ListIdProperty)));
}
set
{
base.SetValue(GetEmails.__ListIdProperty, value);
}
}
public static DependencyProperty __ListItemProperty = System.Workflow.ComponentModel.DependencyProperty.Register("__ListItem", typeof(int), typeof(GetEmails));
[ValidationOption(ValidationOption.Required)]
public int __ListItem
{
get
{
return ((int)(base.GetValue(GetEmails.__ListItemProperty)));
}
set
{
base.SetValue(GetEmails.__ListItemProperty, value);
}
}
public static DependencyProperty __ActivationPropertiesProperty = DependencyProperty.Register("__ActivationProperties", typeof(Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties), typeof(GetEmails));
[ValidationOption(ValidationOption.Required)]
public Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties __ActivationProperties
{
get
{
return (Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties)base.GetValue(GetEmails.__ActivationPropertiesProperty);
}
set
{
base.SetValue(GetEmails.__ActivationPropertiesProperty, value);
}
}
STEP 2: Then in your .actions file add to your block the mappings for those properties (note the entries for __ListID, __ListItem, __Context, and __ActivationProperties):
<Action Name="[DESCRIPTION OF YOUR ACTION]"
ClassName="[Your.Namespace.Goes.Here].GetEmails"
Assembly="[yourDLLName], Version=1.0.0.0, Culture=neutral, PublicKeyToken=0bfc6fa4c4aa913b"
AppliesTo="all"
Category="[Your Category Goes Here]">
<RuleDesigner Sentence="[blah blah blah]">
<FieldBind Field="PeopleFieldName" Text="people field" Id="1"/>
<FieldBind Field="Output" Text="emailAddress" Id="2" DesignerType="parameterNames" />
</RuleDesigner>
<Parameters>
<Parameter Name="__Context" Type="Microsoft.SharePoint.WorkflowActions.WorkflowContext" Direction="In" />
<Parameter Name="__ListId" Type="System.String, mscorlib" Direction="In" />
<Parameter Name="__ListItem" Type="System.Int32, mscorlib" Direction="In" />
<Parameter Name="PeopleFieldName" Type="System.String, mscorlib" Direction="In" />
<Parameter Name="Output" Type="System.String, mscorlib" Direction="Out" />
<Parameter Name="__ActivationProperties" Type="Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties, Microsoft.SharePoint" Direction="Out" />
</Parameters>
</Action>
STEP 3:
Here is an example execute function:
protected override ActivityExecutionStatus Execute(ActivityExecutionContext provider)
{
Output = string.Empty;
try
{
SPWeb web = __Context.Web;
// get all of the information we currently have about the item
// that this workflow is running on
Guid listGuid = new Guid(__ListId);
SPList myList = web.Lists[listGuid];
SPListItem myItem = myList.GetItemById(__ListItem);
//...
}
catch (Exception e)
{
//...
}
return ActivityExecutionStatus.Closed;
}
I'm not sure if this is a change in the 2010 API but the __Context property provides all the necessary pieces, including the list and item. The example below includes #davek's suggestion for discarding the security context:
var contextWeb = __Context.Web;
var site = new SPSite(contextWeb.Url);
var web = site.OpenWeb();
var list = web.Lists[new Guid(__Context.ListId)];
var item = list.GetItemById( __Context.ItemId);
Kit Menke's answer is very comprehensive and covers just about all you need: I would only add the following...
If you do this:
SPWeb tmpweb = __Context.Web;
SPSite site = new SPSite(tmpweb.Url);
SPWeb web = site.OpenWeb();
instead of this:
SPWeb web = __Context.Web;
...
then you are free of the security context passed through to the workflow by the person who triggered it.
Take a look at the SPWorkflowActivationProperties.Item Property
Gets the list item on which the workflow instance is running.
I try this code and runs as well bat the contex objet always is null. some one know why?
protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{
//return base.Execute(executionContext);
int IdRetorno = -1;
try {
SPSecurity.RunWithElevatedPrivileges(delegate
{
LogExceptionToWorkflowHistory("Inicio:", executionContext, WorkflowInstanceId);
using (SPSite sitio = new SPSite(this.__Context.Site.ID))
{
using (SPWeb web = sitio.AllWebs[this.__Context.Site.ID])
{
SPList sourceList = web.Lists[new Guid(ListId)];
LogExceptionToWorkflowHistory(ListId, executionContext, WorkflowInstanceId);
SPList destinoList = web.Lists[new Guid(SourceListId)];
LogExceptionToWorkflowHistory(SourceListId, executionContext, WorkflowInstanceId);
SPListItem sourceItem = sourceList.Items.GetItemById(ListItem);
LogExceptionToWorkflowHistory(ListItem.ToString(), executionContext, WorkflowInstanceId);
SPListItem destinoItem = destinoList.Items.Add();
CopyFieldValues(sourceItem, destinoItem);
destinoItem.SystemUpdate();
sourceItem.Delete();
IdRetorno = destinoItem.ID;
}
}
});
}
catch (Exception ex) {
if (!System.Diagnostics.EventLog.SourceExists("MyApp1"))
System.Diagnostics.EventLog.CreateEventSource(
"MyApp1", "Application");
EventLog EventLog1 = new EventLog();
EventLog1.Source = "MyApp1";
EventLog1.WriteEntry(ex.Message,EventLogEntryType.FailureAudit);
LogExceptionToWorkflowHistory(ex.Message, executionContext, WorkflowInstanceId);
}
OutListItemID = IdRetorno;
return base.Execute(executionContext);
}
thanks
I don't know if this is too easy, but I used:
objCurrentItem = workflowProperties.Item
to get the item within the workflow (a list) and then to alter the items in the list

Resources