I need to configure a Quartz.NET instance using Spring.NET. I haven't been able to find an example of how to do this, other than very simple cases. I don't need any of the job/trigger config since those are done via the API for us. What I need is a means to configure these settings.
quartz.scheduler.instanceName = ServerScheduler
quartz.threadPool.type = Quartz.Simpl.SimpleThreadPool, Quartz
quartz.threadPool.threadCount = 10
quartz.threadPool.threadPriority = Normal
quartz.plugin.xml.type = Quartz.Plugin.Xml.JobInitializationPlugin, Quartz
quartz.plugin.xml.fileNames = C:/Tools/Forge/DataImport/Config/quartz_jobs.xml
quartz.jobStore.type = Quartz.Impl.AdoJobStore.JobStoreTX, Quartz
quartz.jobStore.driverDelegateType = Quartz.Impl.AdoJobStore.StdAdoDelegate, Quartz
quartz.jobStore.dataSource = ForgePlatformDatasource
quartz.dataSource.ForgePlatformDatasource.connectionString = Server=172.20.0.113 Database=ForgeQuartz;Uid=sa;Pwd=654321
quartz.dataSource.ForgePlatformDatasource.provider = SqlServer-40
quartz.jobStore.useProperties = true
quartz.scheduler.exporter.type = Quartz.Simpl.RemotingSchedulerExporter, Quartz
quartz.scheduler.exporter.port = 555
quartz.scheduler.exporter.bindName = QuartzScheduler
quartz.scheduler.exporter.channelType = tcp
According to what I remember you can set all your config details on the SchedulerFactoryObject -> QuartzProperties property.
<object name="SomeName" type="Spring.Scheduling.Quartz.SchedulerFactoryObject, Spring.Scheduling.Quartz">
<property name="QuartzProperties">
<dictionary>
<entry key="quartz.scheduler.instanceName" value="ServerScheduler"/>
<entry key="quartz.threadPool.type" value="Quartz.Simpl.SimpleThreadPool, Quartz"/>
<entry key="quartz.threadPool.threadCount" value="10"/>
... and many more ...
</dictionary>
</property>
</object>
The API-Documentation:
/// <summary>
/// Set Quartz properties, like "quartz.threadPool.type".
/// </summary>
/// <remarks>
/// Can be used to override values in a Quartz properties config file,
/// or to specify all necessary properties locally.
/// </remarks>
/// <seealso cref="ConfigLocation" />
public virtual IDictionary QuartzProperties
{
set { quartzProperties = value; }
}
Related
I am consuming WCF Data Service as Following:
DataMan.ContextWrapper context = new DataMan.ContextWrapper(new Uri("http://localhost:2060/PCM/DataMan.svc/rest/"));
DataMan.Report newReport = DataMan.Report.CreateReport("123123123123", DateTime.Now, "999.199905171156550187000.25");
newReport.Title = "tt";
newReport.StudyAcDate = Convert.ToDateTime("2016-05-04 12:09:00");
newReport.Body = "asdasd";
newReport.Auther = "ali.h";
newReport.ApproverComment = "cm";
newReport.Approver = "admin";
context.AddToReports(newReport);
DataServiceResponse response = context.SaveChanges();
but after calling SaveChange() I have got the following error:
The server encountered an error processing the request. The exception message is 'Incoming message for operation 'ProcessRequestForMessage' (contract 'IRequestHandler' with namespace 'http://tempuri.org/') contains an unrecognized http body format value 'Xml'. The expected body format value is 'Raw'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details.'. See server logs for more details.
and my WCF Data Service is as following:
public class ContextWrapper : DataAccessDbContext
{
public ContextWrapper() : base("connection string")
{
}
}
[JSONPSupportBehavior]
public class DataMan : EntityFrameworkDataService<ContextWrapper>
{
public static void InitializeService(DataServiceConfiguration config)
{
config.SetEntitySetAccessRule("*", EntitySetRights.All);
config.SetEntitySetAccessRule("Studies", EntitySetRights.None);
config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
config.UseVerboseErrors = true; // TODO - Remove for production?
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3;
}
protected override void HandleException(HandleExceptionArgs args)
{
base.HandleException(args);
}
}
I also implemented and configured WebContentTypeMapper to bypass mentioned Error as following:
public class ContentTypeMapper : WebContentTypeMapper
{
public override WebContentFormat GetMessageFormatForContentType(string contentType)
{
return WebContentFormat.Raw;
}
}
Custom binding:
<binding name="XmlMapper">
<webMessageEncoding webContentTypeMapperType="MARCO.SOA.PCMServiceLib.ContentTypeMapper,MARCO.SOA.PCMServiceLib.Core"/>
<httpTransport manualAddressing="true"/>
</binding>
</customBinding>
Service endpoint:
<service behaviorConfiguration="Commom2.Behavior" name="MARCO.SOA.PCMServiceLib.DataMan">
<endpoint address="rest" behaviorConfiguration="Rest.Behavior" binding="webHttpBinding"
bindingConfiguration="XmlMapper" contract="System.Data.Services.IRequestHandler">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<host>
<baseAddresses>
<add baseAddress="http://localhost:2060/PCM/DataMan.svc"/>
</baseAddresses>
</host>
</service>
but it still get exception, I think something went wrong with my configuration.
Any help would be truly appreciated.
Thanks in advance.
okay, after much trouble I finally solved the problem,
so we need to initiate factory property for serviceActivation
So my relative address was:
<serviceHostingEnvironment>
<serviceActivations>
.
.
.
<add relativeAddress="DataMan.svc" service="MARCO.SOA.PCMServiceLib.DataMan"/>
.
.
.
</serviceActivations>
</serviceHostingEnvironment>
and I have changed it to
<serviceHostingEnvironment>
<serviceActivations>
.
.
.
<add relativeAddress="DataMan.svc" service="MARCO.SOA.PCMServiceLib.DataMan" factory="System.Data.Services.DataServiceHostFactory, Microsoft.Data.Services, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
.
.
.
</serviceActivations>
</serviceHostingEnvironment>
now everything is now working nice.
more info about DataServiceHostFactory
Note:
By this we don't need to override GetMessageFormatForContentType of WebContentTypeMapper and force it to return WebContentFormat.Raw or another content format and don't need any customBinding in config file.
Thanks to all.
I've tried a 1000 different options an permutations.
Why can't compile my Cat mapping?
Exception thrown: 'NHibernate.MappingException' in NHibernate.dll
Additional information: Could not compile the mapping document: (string)
Configuration cfg = new Configuration();
cfg.Configure();
cfg.AddXmlString(
#"<?xml version=""1.0"" encoding=""utf - 8"" ?>"
+ #"<hibernate-mapping xmlns=""urn:nhibernate-mapping-2.2"" assembly=""QuickStart"" namespace=""QuickStart.Cat"">"
+ #"<class name=""Cat"" table=""Cat"">"
+ #" <id name=""Id"" ><column name=""CatId"" /><generator class=""uuid.hex"" /></id>"
//+ #" <id name=""Id"" ><column name=""CatId"" sql-type=""char(32)"" not-null=""true"" /><generator class=""uuid.hex"" /></id>"
//+ #" <property name=""Name"" ><column name=""Name"" length=""16"" not-null=""true"" /></property>"
//+ #" <property name=""Sex"" />"
//+ #" <property name=""Weight"" />"
+ #"</class>"
+ #"</hibernate-mapping>"
);
--- from Web.Config
NHibernate.Connection.DriverConnectionProvider
NHibernate.Driver.SqlClientDriver
NHibernate.Dialect.MsSql2012Dialect
Server=localhost;initial catalog=PlaygroundDB;Integrated Security=True
encoding=""utf - 8"" ?> should be encoding=""utf-8""?>
But I never add xml mapping programmaticaly one by one. And even less as raw string (which is quite prone to errors). Instead, I add ClassName.hbm.xml files in project, setting their Build action property to Embedded resource, and I call .AddAssembly(MyProjectAssembly) before building the configuration.
If your mappings are embedded in the same assembly defining your session factory, the code is as simple as:
public static class NHibernateSessionFactory
{
private static readonly ISessionFactory _sessionFactory;
static NHibernateSessionFactory()
{
var configuration = new Configuration();
configuration.Configure();
configuration.AddAssembly(typeof(NHibernateSessionFactory).Assembly);
_sessionFactory = configuration.BuildSessionFactory();
}
public static ISessionFactory Instance { get { return _sessionFactory; } }
}
Minimal configuration file (hibernate.cfg.xml) I am using:
<?xml version="1.0" encoding="utf-8"?>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory name="ProjectName">
<property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
<property name="connection.connection_string_name">ProjectConnectionStringName</property>
<property name="dialect">NHibernate.Dialect.MsSql2012Dialect</property>
<property name="adonet.batch_size">100</property>
<property name="prepare_sql">true</property>
</session-factory>
</hibernate-configuration>
ProjectConnectionStringName refers to a connection string defined in .Net standard configuration connectionStrings node.
How to Integrate Struts Conventions with Tiles while maintaining conventions benefits?
The issue is that conventions links url-to-action-to-result automatically and does this nicely for jsp, velocity and freemarker results. It does not expect to deal with a tiles result.
When using tiles we typically want all our UI actions (as opposed the json/xml service actions) to use tiles but in doing so we lose the convention for the result component and need to use annotations. Annotations allow us to deviate from the expected, but in a large application when expecting to use tiles this is an annoyance. Further conventions allows us to create actions by only specifying a view. We would want to retain such benefit when using tiles as well. To rectify this we need to establish a convention that carries though to the tiles result such that we don't need to use annotations to tie the action to the tiles result and that we can continue to create JSPs without actions classes which will gain the benefits of conventions (no xml) and the benefits of tiles (all the boiler plate is factored into tiles).
How to achieve this?
This is a self answer to help others who wish to address this issue
Here are the steps needed:
Create custom tiles result which dynamically builds a "location" string (the location string is the value passed to tiles) which takes into account the namespace, actionName.
Create a package which uses this result (named "tiles") and have conventions use that as it's parent package
Implement and register a "com.opensymphony.xwork2.UnknownHandler", this step is the most critical as this handler is called when the result can't be resolved
Tiles definition(s) which make use of "location" passed in from the first step
The above steps require the following in struts.xml
<struts>
<constant name="struts.convention.default.parent.package" value="tiles-package"/>
<bean type="com.opensymphony.xwork2.UnknownHandler" name="tilesUnknownHandler" class="com.kenmcwilliams.tiles.result.TilesUnknownHandler"/>
<package name="tiles-package" extends="convention-default">
<result-types>
<result-type default="true" name="tiles" class="com.kenmcwilliams.tiles.result.TilesResult"/>
</result-types>
</package>
</struts>
Custom result-type implementation:
package com.kenmcwilliams.tiles.result;
import com.opensymphony.xwork2.ActionInvocation;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.dispatcher.ServletDispatcherResult;
import org.apache.tiles.TilesContainer;
import org.apache.tiles.access.TilesAccess;
import org.apache.tiles.request.ApplicationContext;
import org.apache.tiles.request.servlet.ServletRequest;
import org.apache.tiles.request.servlet.ServletUtil;
public class TilesResult extends ServletDispatcherResult {
private static final Logger log = Logger.getLogger(TilesResult.class.getName());
public TilesResult() {
super();
}
public TilesResult(String location) {
super(location);
}
#Override
public void doExecute(String location, ActionInvocation invocation) throws Exception {
//location = "test.definition"; //for test
log.log(Level.INFO, "TilesResult doExecute() location: {0}", location);
//Start simple conventions
//
if (/** tiles && **/location == null) {
String namespace = invocation.getProxy().getNamespace();
String actionName = invocation.getProxy().getActionName();
location = namespace + "#" + actionName + ".jsp"; //Warning forcing extension
log.log(Level.INFO, "TilesResult namespace: {0}", namespace);
log.log(Level.INFO, "TilesResult actionName: {0}", actionName);
log.log(Level.INFO, "TilesResult location: {0}", location);
}
//End simple conventions
setLocation(location);
ServletContext context = ServletActionContext.getServletContext();
ApplicationContext applicationContext = ServletUtil.getApplicationContext(context);
TilesContainer container = TilesAccess.getContainer(applicationContext);
HttpServletRequest request = ServletActionContext.getRequest();
HttpServletResponse response = ServletActionContext.getResponse();
ServletRequest servletRequest = new ServletRequest(applicationContext, request, response);
container.render(location, servletRequest);
}
}
TilesUnknownHandler Implementation:
package com.kenmcwilliams.tiles.result;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ObjectFactory;
import com.opensymphony.xwork2.Result;
import com.opensymphony.xwork2.XWorkException;
import com.opensymphony.xwork2.config.Configuration;
import com.opensymphony.xwork2.config.entities.ActionConfig;
import com.opensymphony.xwork2.config.entities.ResultConfig;
import com.opensymphony.xwork2.config.entities.ResultConfig.Builder;
import com.opensymphony.xwork2.inject.Container;
import com.opensymphony.xwork2.inject.Inject;
import flexjson.JSONSerializer;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletContext;
import org.apache.commons.lang.StringUtils;
import org.apache.struts2.convention.ConventionUnknownHandler;
public class TilesUnknownHandler extends ConventionUnknownHandler {
private static final Logger log = Logger.getLogger(TilesUnknownHandler.class.getName());
private static final String conventionBase = "/WEB-INF/content";
#Inject
public TilesUnknownHandler(Configuration configuration, ObjectFactory objectFactory,
ServletContext servletContext, Container container,
#Inject("struts.convention.default.parent.package") String defaultParentPackageName,
#Inject("struts.convention.redirect.to.slash") String redirectToSlash,
#Inject("struts.convention.action.name.separator") String nameSeparator) {
super(configuration, objectFactory, servletContext, container, defaultParentPackageName,
redirectToSlash, nameSeparator);
log.info("Constructed TilesUnknownHandler");
}
#Override
public ActionConfig handleUnknownAction(String namespace, String actionName)
throws XWorkException {
ActionConfig actionConfig;
log.info("TilesUnknownHandler: before handleUnknownAction");
ActionConfig handleUnknownAction = super.handleUnknownAction(namespace, actionName);
log.info("TilesUnknownHandler: after handleUnknownAction, returning with:");
log.log(Level.INFO, "...ActionConfig value: {0}", (new JSONSerializer().serialize(handleUnknownAction)));
log.log(Level.INFO, "Modifying handleUnknowAction result handler");
Map<String, ResultConfig> results = handleUnknownAction.getResults();
ResultConfig resultConfig = results.get("success");
Builder builder = new ResultConfig.Builder("com.opensymphony.xwork2.config.entities.ResultConfig", "com.kenmcwilliams.tiles.result.TilesResult");
Map<String, String> params = resultConfig.getParams();
String tilesResultString = null;
String location = params.get("location");
if (location != null && !location.isEmpty()) {
int length = conventionBase.length();
if(StringUtils.startsWith(location, conventionBase)){
String subString = location.substring(length); //chop off "/WEB-INF/content"
int count = StringUtils.countMatches(subString, "/");//TODO: maybe check for "//", although I don't know why it would be in the string
if (count == 1){//empty namespace
tilesResultString = subString.replaceFirst("/", "#"); //TODO: because I am doing a straight replacement of the last element the else can probably be removed
}else{ //replace the last slash between the namespace and the file with "#"
int lastIndex = subString.lastIndexOf("/");
//subString.substring(lastIndex, lastIndex);
String nameSpace = subString.substring(0, lastIndex);
String file = subString.substring(lastIndex + 1);
tilesResultString = nameSpace + "#" + file;
}
}
}
Map<String, String> myParams = new LinkedHashMap<String, String>();
myParams.put("location", tilesResultString);
builder.addParams(myParams);
ResultConfig build = builder.build();
Map<String, ResultConfig> myMap = new LinkedHashMap<String, ResultConfig>();
myMap.put("success", build);
log.log(Level.INFO, "\n\n...results: {0}\n\n", (new JSONSerializer().serialize(results)));
actionConfig = new ActionConfig.Builder(handleUnknownAction).addResultConfigs(myMap).build();
//className("com.kenmcwilliams.tiles.result.TilesResult")
return actionConfig;
}
#Override
public Result handleUnknownResult(ActionContext actionContext, String actionName,
ActionConfig actionConfig, String resultCode) throws XWorkException {
log.info("TilesUnknownHandler: before handleUnknownResult");
Result handleUnknownResult = super.handleUnknownResult(actionContext, actionName, actionConfig, resultCode);
log.info("TilesUnknownHandler: after handleUnknownResult, returning with:");
log.log(Level.INFO, "...Result value: {0}", (new JSONSerializer().serialize(handleUnknownResult)));
return handleUnknownResult;
}
}
An example of how to use our "location" string which is in the form of: NameSpace + "#" + ActionName + ".jsp", note this definition <definition name="REGEXP:(.*)#(.*)" extends="default"> in the following:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE tiles-definitions PUBLIC "-//Apache Software Foundation//DTD Tiles Configuration 3.0//EN" "http://tiles.apache.org/dtds/tiles-config_3_0.dtd">
<tiles-definitions>
<definition name="default" template="/WEB-INF/template/template.jsp">
<put-list-attribute name="cssList" cascade="true">
<add-attribute value="/style/cssreset-min.css" />
<add-attribute value="/style/cssfonts-min.css" />
<add-attribute value="/style/cssbase-min.css" />
<add-attribute value="/style/grids-min.css" />
<add-attribute value="/script/jquery-ui-1.8.24.custom/css/ui-lightness/jquery-ui-1.8.24.custom.css" />
<add-attribute value="/style/style.css" />
</put-list-attribute>
<put-list-attribute name="jsList" cascade="true">
<add-attribute value="/script/jquery/1.8.1/jquery.min.js" />
<add-attribute value="/script/jquery-ui-1.8.24.custom/js/jquery-ui-1.8.24.custom.min.js" />
<add-attribute value="/script/jquery.sort.js" />
<add-attribute value="/script/custom/jquery-serialize.js" />
</put-list-attribute>
<put-attribute name="title" value="defaults-name" cascade="true" type="string"/>
<put-attribute name="head" value="/WEB-INF/template/head.jsp"/>
<put-attribute name="header" value="/WEB-INF/template/header.jsp"/>
<put-attribute name="body" value="/WEB-INF/template/body.jsp"/>
<put-attribute name="footer" value="/WEB-INF/template/footer.jsp"/>
</definition>
<definition name="REGEXP:(.*)#(.*)" extends="default">
<put-attribute name="title" cascade="true" expression="OGNL:#com.opensymphony.xwork2.ActionContext#getContext().name"/>
<put-attribute name="body" value="/WEB-INF/content{1}/{2}"/>
</definition>
</tiles-definitions>
With this in place you can create JSP's under /WEB-INF/content/someplace/my-action.jsp
Just as you would with conventions AND tiles will decorate it appropriately as well if you create an action class called com.myapp.action.someplace.MyAction without any result type this code will execute and the /WEB-INF/content/someplace/my-action.jsp result would still be rendered.
There you have it conventions + tiles with no more annotations (well for the normal case).
NOTES:
This answer certainly isn't perfect but it does provide a working example of the strategy which can be applied to other view technologies (sitemesh, others).
Currently you can see the ".jsp" is being appended in the tiles result NOT in the tiles definitions this is inflexible. The specific extension should be specified within tiles, that is the body attribute within the definition should append the specific view type (.jsp, .fml, .vm) because you should know best at that time.
It is important to note that definitions are tried in the order they are given,so you can override the normal case REGEXP:(.*)#(.*) by placing definitions between the default and REGEXP:(.*)#(.*) definitions. For instance a definition called authenticated\(.*) can be placed between these two definitions. After all if you couldn't do this and all pages had to be tiled the same we really wouldn't be using tiles!
Just so you know when using tiles3 (the struts2 tiles3 plugin) you can use all three types of view technologies (jsp, freemarker, velocity) to compose one tile. It works. You are probably going to use one view technology consistently but it's nice to know it is possible.
I have successfully created a working custom STS using the project templates for the passive and active cases that came with the most recent WIF SDK (for .NET 4.0). Everything works as desired.
I am now trying to upgrade my web applications and services to .NET 4.5, including my custom STS. I have been able to map all of the namespaces/classes from Microsoft.IdentityModel.xxx to the new namespaces/classes built into the framework with 1 exception - WSTrustServiceHostFactory.
That class no longer seems to exist, and I cannot figure out how to replace the functionality it provided. Namely, from this link:
http://msdn.microsoft.com/en-us/library/microsoft.identitymodel.protocols.wstrust.wstrustservicehostfactory
<%#ServiceHostLanguage="C#"Debug="true"Service="XXX.XXX.MyActiveSTSConfiguration"Factory="Microsoft.IdentityModel.Protocols.WSTrust.WSTrustServiceHostFactory"%>
My passive STS is currently working after upgrading to 4.5. I need to find an appropriate/recommended method of instantiating an active SecurityTokenService using the 4.5 framework (ideally, using web.config for most configuration as in the SDK project templates). Any suggestions are appreciated.
This turned out to be pretty simple once I figured a few things out.
Service host markup:
<%# ServiceHost Language="C#" Debug="true" Service="XXX.XXX.MyActiveSTSConfiguration" Factory="XXX.XXX.CustomWSTrustServiceHostFactory" %>
Here's my custom factory class implementation. The key is that since you can no longer use WSTrustServiceFactory to create a WSTrustServiceHost for you, you have to explicitly create one yourself in the CreateServiceHost method overrides.
public class CustomWSTrustServiceHostFactory
: ServiceHostFactory {
/// <summary>
/// Initializes a new instance of the <see cref="CustomWSTrustServiceHostFactory"/> class.
/// </summary>
public CustomWSTrustServiceHostFactory()
: base() { }
/// <summary>
/// Creates and configures a <see cref="WSTrustServiceHost"/> with a specific base address.
/// </summary>
/// <param name="serviceType">Specifies the type of service to host (ignored).</param>
/// <param name="baseAddresses">The <see cref="T:Uri"/> array that contains the base addresses for the service.</param>
/// <returns>A <see cref="WSTrustServiceHost"/> with a specific base address.</returns>
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses) {
var config = new PortalActiveSTSConfiguration();
var host = new WSTrustServiceHost(config, baseAddresses);
//var host = base.CreateServiceHost(serviceType, baseAddresses);
var serviceBehavior = host.Description.Behaviors.Find<ServiceBehaviorAttribute>();
serviceBehavior.AddressFilterMode = AddressFilterMode.Any;
return host;
}
/// <summary>
/// Creates and configures a <see cref="WSTrustServiceHost"/> with a specific base address.
/// </summary>
/// <param name="constructorString">The constructor string (ignored).</param>
/// <param name="baseAddresses">The <see cref="T:Uri"/> array that contains the base addresses for the service.</param>
/// <returns></returns>
public override ServiceHostBase CreateServiceHost(string constructorString, Uri[] baseAddresses) {
var config = new PortalActiveSTSConfiguration();
var host = new WSTrustServiceHost(config, baseAddresses);
//var host = base.CreateServiceHost(constructorString, baseAddresses);
var serviceBehavior = host.Description.Behaviors.Find<ServiceBehaviorAttribute>();
serviceBehavior.AddressFilterMode = AddressFilterMode.Any;
return host;
}
}
Custom service configuration class implementation (basically what came with the WIF 4.0 STS template):
public class MyActiveSTSConfiguration
: SecurityTokenServiceConfiguration {
public MyActiveSTSConfiguration()
: base(
WebConfigurationManager.AppSettings[ISSUER_NAME],
new X509SigningCredentials(
CertificateUtil.GetCertificate(
StoreName.My, StoreLocation.LocalMachine, X509FindType.FindByThumbprint,
WebConfigurationManager.AppSettings[SIGNING_CERTIFICATE_THUMBPRINT],
true)
)
) {
this.SecurityTokenService = typeof(MyActiveSTS);
}
}
I'm trying develop a custom control for a WinRT/Metro application.
It has a dependency property and I would like to be able to set its value within the custom control. However, using SetValue breaks any bindings that consumers of the control may have created.
None of the solutions I've found (e.g. SetCurrentValue) seem to apply to WinRT/Metro. Is there a solution to this?
It sounds like a simple thing to do and - honestly! - I've tried to find a solution here and elsewhere. Any help would be greatly appreciated.
You can set the default value in PropertyMetadata (Dr. WPF's snippets to the rescue!).
#region IsAvailable
private static bool DefaultIsAvailable = false;
/// <summary>
/// IsAvailable Dependency Property
/// </summary>
public static readonly DependencyProperty IsAvailableProperty =
DependencyProperty.Register(
"IsAvailable",
typeof(bool),
typeof(CustomControl1),
new PropertyMetadata(DefaultIsAvailable, OnIsAvailableChanged));
/// <summary>
/// Gets or sets the IsAvailable property. This dependency property
/// indicates ....
/// </summary>
public bool IsAvailable
{
get { return (bool)GetValue(IsAvailableProperty); }
set { SetValue(IsAvailableProperty, value); }
}
/// <summary>
/// Handles changes to the IsAvailable property.
/// </summary>
/// <param name="d">
/// The <see cref="DependencyObject"/> on which
/// the property has changed value.
/// </param>
/// <param name="e">
/// Event data that is issued by any event that
/// tracks changes to the effective value of this property.
/// </param>
private static void OnIsAvailableChanged(
DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var target = (CustomControl1)d;
bool oldIsAvailable = (bool)e.OldValue;
bool newIsAvailable = target.IsAvailable;
target.OnIsAvailableChanged(oldIsAvailable, newIsAvailable);
}
/// <summary>
/// Provides derived classes an opportunity to handle changes
/// to the IsAvailable property.
/// </summary>
/// <param name="oldIsAvailable">The old IsAvailable value</param>
/// <param name="newIsAvailable">The new IsAvailable value</param>
protected virtual void OnIsAvailableChanged(
bool oldIsAvailable, bool newIsAvailable)
{
}
#endregion
EDIT*
If you want to change the value - you can, but if you use a basic binding that is OneWay - i.e. - it takes the value from a binding source and sets it to the dependency property - the binding will stop working because source and target values won't be synchronized any more.
If you set Mode="TwoWay" - the binding source will be updated when the binding target (your control) modifies the dependency property, so the binding will remain valid and will continue working both ways.