none
Make field required on IR and SR forms: SCSM 2012

    Question

  • I have an issue where technicians where I am that use SCSM have a tendency not to fill out fields on SRs and IRs that I need to have populated for reporting. I'd like to know how to make certain fields (and especially custom fields) mandatory. I'm new to the authoring tool and find it beyond frustrating as is, and can't for the life of me find this option anywhere.

    I know in our 2010 install we had several mandatory fileds on the form, but none of those restrictions appear in 2012 that I can see.

    Monday, January 28, 2013 6:51 PM

Answers

  • You need to create a custom control using Visual Studio that you add to the SR and IR forms. You then need to find the controls and add validation rules for them. Once this is done, the controls will have the little red asterisk next to them when they are not filled out and the OK button will be disabled.


    Rob Ford scsmnz.net
    Cireson www.cireson.com
    For a free SCSM 2012 Auto-Close app click here

    Friday, February 01, 2013 9:20 PM
    Moderator

All replies

  • You need to create a custom control using Visual Studio that you add to the SR and IR forms. You then need to find the controls and add validation rules for them. Once this is done, the controls will have the little red asterisk next to them when they are not filled out and the OK button will be disabled.


    Rob Ford scsmnz.net
    Cireson www.cireson.com
    For a free SCSM 2012 Auto-Close app click here

    Friday, February 01, 2013 9:20 PM
    Moderator
  • Thanks Rob, that points me in the general direction. I don't suppose anyone has blogged about this or there is documentation available somewhere?
    Saturday, February 02, 2013 12:39 AM
  • Take a look at my blog here on creating a control to disable form controls:

    http://scsmnz.net/service-manager-2012-how-to-disable-form-controls-for-a-resolved-or-closed-incident-part-1/

    You can create a very similar control that specifically looks for the type and name of controls (name can be seen in AT) that you wish to set validation for.

    Where I disable controls in this code, you would add validation rules as required.

    For example, after you get a reference to a TextBox you could add a validation rule like this:

    binding = BindingOperations.GetBinding(yourtextBox, TextBox.TextProperty);
    binding.ValidationRules.Clear();
    TextRule textrule = new TextRule();
    binding.ValidationRules.Add(rule);

    The validation rule TextRule is defined like this:

    public class TextRule : System.Windows.Controls.ValidationRule
    {
        public TextRule()
        {
        }
    
        public override ValidationResult Validate(object value, CultureInfo cultureInfo)
        {
            try
            {
                if (value == null || (string)value == "") return new ValidationResult(false, null);
            }
            catch
            {
                return new ValidationResult(false, null);
            }
            return new ValidationResult(true, null);
        }
    }

    This rule will force the TextBox to contain text before you can click ok, for example.

    Rob Ford scsmnz.net
    Cireson www.cireson.com
    For a free SCSM 2012 Auto-Close app click here



    Saturday, February 02, 2013 4:24 AM
    Moderator
  • Hi Rob.Ford, great post!

    I use this solution for set urgency and impact values:

    inst["Impact"] = emg.EntityTypes.GetEnumeration(new Guid("8f1a713e-53aa-9d8a-31b9-a9540074f305"));
    inst["Urgency"] = emg.EntityTypes.GetEnumeration(new Guid("725a4cad-088c-4f55-a845-000db8872e01"));


    Monday, April 15, 2013 5:54 PM
  • I am able to get the incident form disabling piece working just great.  My next step is trying to add some required fields per your instructions above.  I feel like I am close to the answer but am stuck at the moment.  In your "Form Disabling" example you are binding to the control by using:

      <TextBox Height="0" Margin="0,0,0,0" Name="textId" VerticalAlignment="Top" Width="0" Text="{Binding Path=$Id$, Mode=OneWay}" Visibility="Collapsed" />

    Should this be the same when setting up Required Fields?  I'm having trouble with the step above that says "after you get a reference to a textbox".  To me, it seems like the Binding Path should be changed to Description as this is the name of the binding when you open the Change Request form in the AT.  Then you would use the Name (textId) to plug into the binding variable in the .cs code.

    XAML

      <TextBox Height="0" Margin="0,0,0,0" Name="textId" VerticalAlignment="Top" Width="0" Text="{Binding Path=Description, Mode=OneWay}" Visibility="Collapsed" />

    C#

    binding = BindingOperations.GetBinding(textID, TextBox.TextProperty);
    binding
    .ValidationRules.Clear();
    TextRule textrule = new TextRule();
    binding
    .ValidationRules.Add(textrule);

    Friday, September 20, 2013 7:33 PM
  • Leave the binding as it is and in the DataContext Changed event:

    //Check if in template mode
    if (FormUtilities.Instance.IsFormInTemplateMode(this)) return;
    
    //Check for valid IDataItem
    if (this.DataContext != null && this.DataContext is IDataItem)
    {
    }
    

    If the textbox you want to validate is in your control, you can simply add your validation now.

    If it needs to be applied to an existing control on the incident form, you need to find that control using the WPF logical/visual tree, get a reference to it and then add your validation:

    //Get tab item
    DependencyObject doTabControl = GetParentDependancyObject(this, "System.Windows.Controls.TabControl");
    TabControl tc = (TabControl)doParentRoot;
    TabItem tabitem_general = (TabItem)tc.FindName("TabItem_General");
    
    //Get your textbox that exists on the general tab
    TextBox textbox = (TextBox)tabitem_general.FindName("textbox1"); 
    
    //Add validation to textbox now
    
    //Returns specified parent object, if found, if name is empty, then navigate to top
    private DependencyObject GetParentDependancyObject(DependencyObject child, string name)
    {
        try
        {
            //We need the logical tree to get our parent
            DependencyObject parent = LogicalTreeHelper.GetParent(child);
            DependencyObject lastparent = null;
    
            //Is the parent our specified control?
            if (name != "" && parent.GetType().ToString() == name) return parent;
    
            //No, process further
            while (parent != null)
            {
                string s = parent.GetType().ToString();
                if (s == name && name != "") return parent;
                parent = LogicalTreeHelper.GetParent(parent);
                if (parent != null) lastparent = parent;
            }
            //Return results
            if (name != "") return null;
            else return lastparent;
        }
        catch
        {
            return null;
        }
    }
    

     


    Rob Ford scsmnz.net
    Cireson www.cireson.com
    For a free SCSM 2012 Notify Analyst app click here

    Sunday, September 22, 2013 9:45 PM
    Moderator
  • That worked...thank you very much for you help here!

    Steve

    Monday, September 23, 2013 11:29 PM
  • I tried the above instructions and do not get errors but the fields are not required. 

    Here is my XAML.CS:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    
    using System.ComponentModel;
    using System.ComponentModel.Design;
    using Microsoft.EnterpriseManagement;
    using Microsoft.EnterpriseManagement.Common;
    using Microsoft.EnterpriseManagement.Configuration;
    using Microsoft.EnterpriseManagement.UI.DataModel;
    using Microsoft.EnterpriseManagement.UI.SdkDataAccess;
    using Microsoft.EnterpriseManagement.ConsoleFramework;
    using Microsoft.EnterpriseManagement.UI.WpfControls;
    using System.Globalization;
    
    namespace RequiredFieldForm
    {
        public partial class RequiredFieldFormControl : UserControl
        {
            // Current Session:
            private EnterpriseManagementGroup emg = null;
    
            // Current Instance:
            private IDataItem inst = null;
    
            // List of Textbox Controls to apply validation rules:
            private List<string> fieldNameList = new List<string>()
    	        {
    	            "TextBox_1",    // Sales Force ID
    	            "titleTextBox"  // Title
    	        };
            
            public RequiredFieldFormControl()
            {
                InitializeComponent();
    
                // Connect to the current console session
                this.emg = GetSession();
            }
    
            private EnterpriseManagementGroup GetSession()
            {
                // Get the current console session management group
                IServiceContainer container = (IServiceContainer)FrameworkServices.GetService(typeof(IServiceContainer));
                Microsoft.EnterpriseManagement.UI.Core.Connection.IManagementGroupSession curSession =
                    (Microsoft.EnterpriseManagement.UI.Core.Connection.IManagementGroupSession)container.GetService(typeof(Microsoft.EnterpriseManagement.UI.Core.Connection.IManagementGroupSession));
                return curSession.ManagementGroup;
            }
    
            private void RequiredFieldFormControl_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
            {
                if (this.DataContext is IDataItem)
                {
                    inst = (IDataItem)this.DataContext;
    
                    AddValidationRules();
                }
            }
    
            private void AddValidationRules()
            {
                DependencyObject doParentRoot = GetParentDependancyObject(this, "System.Windows.Controls.TabControl");
                TabControl tc = (TabControl)doParentRoot;
                TabItem tabitem_general = (TabItem)tc.FindName("TabItem_General");
    
                // Iterate the TextBox names in our list defined at the top:
                foreach (String textBoxName in fieldNameList)
                {
                    TextBox textbox = (TextBox)tabitem_general.FindName(textBoxName);
                    addTextBoxRule(textbox);
                }
            }
    
            private void addTextBoxRule(TextBox tb)
            {
                try
                {
                    Binding binding = BindingOperations.GetBinding(tb, TextBox.TextProperty);
                    binding.ValidationRules.Clear();
                    TextBoxRule rule = new TextBoxRule();
                    binding.ValidationRules.Add(rule);
                }
                catch (Exception ex)
                {
                    //MessageBox.Show("ERROR: " + ex.Message);
                }
            }
    
            //Returns specified parent object, if found, if name is empty, then navigate to top
            private DependencyObject GetParentDependancyObject(DependencyObject child, string name)
            {
                try
                {
                    //We need the logical tree to get our parent
                    DependencyObject parent = LogicalTreeHelper.GetParent(child);
                    DependencyObject lastparent = null;
    
                    //Is the parent our specified control?
                    if (name != "" && parent.GetType().ToString() == name) return parent;
    
                    //No, process further
                    while (parent != null)
                    {
                        string s = parent.GetType().ToString();
                        if (s == name && name != "") return parent;
                        parent = LogicalTreeHelper.GetParent(parent);
                        if (parent != null) lastparent = parent;
                    }
                    //Return results
                    if (name != "") return null;
                    else return lastparent;
                }
                catch
                {
                    return null;
                }
            }
    
        }
    
        public class TextBoxRule : ValidationRule
        {
            public TextBoxRule()
            {
            }
    
            public override ValidationResult Validate(object value, CultureInfo cultureInfo)
            {
                try
                {
                    if (value == null || ((string)value) == "") return new ValidationResult(false, null);
                    else return new ValidationResult(true, null);
                }
                catch
                {
                    return new ValidationResult(false, null);
                }
            }
        }
    }
    
    Here is the XAML:
    <UserControl x:Class="RequiredFieldForm.RequiredFieldFormControl"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                 mc:Ignorable="d"
                 Visibility="Collapsed"
                 Width="Auto" Height="Auto" DataContextChanged="RequiredFieldFormControl_DataContextChanged" >
        <Grid Height="Auto" Width="Auto">
            <TextBox Height="0" Margin="0,0,0,0" Name="textId" VerticalAlignment="Top" Width="0" Text="{Binding Path=$Id$, Mode=OneWay}" Visibility="Collapsed" />
        </Grid>
    </UserControl>

    Here is the control syntax for titleTextBox in the MP XML:
    <AddControl Object="titleTextBox" Assembly="RequiredFieldFormControl" Type="RequiredFieldForm.RequiredFieldFormControl" />

    And finally here is the Resource section of the MP XML:
    <Assembly ID="RequiredFieldFormControl" Accessibility="Public" QualifiedName="RequiredFieldFormControl" FileName="RequiredFieldFormControl.dll" />

    Any ideas?
    Monday, October 14, 2013 12:37 AM
  • I figured out my mistake and am running into another issue.

    After following the instructions more carefully I created a label and replaced the code with:

    <AddControl Parent="generalTabGrid" Assembly="RequiredFieldFormControl" Type="RequiredFieldForm.RequiredFieldFormControl" Left="49.5" Top="458" Right="0" Bottom="0" Row="0" Column="0" />   

    As you can see in my previous post I am trying to make titleTextBox and TextBox_1 required.  TextBox_1 is a custom field that I add to the CR form.  The MP DLL bundle import without issue but when I create a CR the app crashes.  For some reason I am getting an error saying TextBox_1 doesn't exist:

    Monday, October 14, 2013 5:28 PM
  • Do you find titleTextBox ok? FindName() can be problematic, for several reasons. This is why I use the method in my post to recursively look for the elements (especially dynamically added ones - i.e. form customisations) as opposed to using FindName().


    Rob Ford scsmnz.net
    Cireson www.cireson.com
    For a free SCSM 2012 Notify Analyst app click here

    Tuesday, October 15, 2013 2:21 AM
    Moderator
  • I did not get it to work yet.  Also, I don't understand why it is causing the application to crash. 
    Tuesday, October 15, 2013 6:26 PM
  • Build your Debug configuration. Copy the output.dll and output.pdb from "Bin\Debug" to "C:\Program Files\Microsoft System Center 2012\Service Manager"

    Start the console.

    In Visual Studio, select Debug\Attach To Process. Select "Microsoft.EnterpriseManagement.ServiceManager.UI.Console.exe" and attach.

    Set a breakpoint on at the start of AddValidationRules().

    Open the form in the console. The breakpoint should be hit. Hit F11 to execute each line one by one and see where the exception occurs that crashes the console.


    Rob Ford scsmnz.net
    Cireson www.cireson.com
    For a free SCSM 2012 Notify Analyst app click here

    Tuesday, October 15, 2013 10:15 PM
    Moderator
  • Got it.  I will post the entire solution to the Gallery.
    Thursday, October 17, 2013 6:00 PM
  • Hi,

    Where can I find the solution ?

    Regards

    Tuesday, October 22, 2013 7:15 AM
  • Testing and refining.  Post coming soon.

    Wednesday, October 23, 2013 2:31 AM
  • Is the solution posted to the TechNet Gallery Herb?
    Monday, November 18, 2013 1:57 PM
  • Tested and working.  Will post this week.
    Tuesday, November 19, 2013 3:14 AM
  • Tested and working.  Will post this week.

    Herb, did you get a chance to post your solution to the Gallery? All I see from you so far is the "All My Work Items" post. Thanks
    Monday, December 23, 2013 2:45 PM
  • No, I have not. I have been hesitant to post because I am not sure if I am aloud to include the SCSM DLLs that are required for this solution.

    If you have SCSM you will have the DLLs but I am not sure how MS will feel if I include them in my post.

    Thoughts?

    Thursday, December 26, 2013 3:00 PM
  • I uploaded the zip file to my google drive for now. This should get you 95% of the way there.  You just need to add some info to your MP and you're all set.


    Thursday, December 26, 2013 3:14 PM
  • Hello,

    I want to update some Existing fields like Priority, Impact as MANDATORY field in the Change request form.

    As i'm new to SCSM tool I'm unable to proceed with that. Please share experts advice to achieve this.

    Regards,

    Vijay

    Wednesday, December 23, 2015 4:21 PM
  • Here I had from a couple years ago.  Everything you need should be here:

    https://onedrive.live.com/redir?resid=956A3B515A90E99B%21151

    Also, you should go through this post if you need more detail.

    Monday, December 28, 2015 3:43 PM
  • Take a look at my blog here on creating a control to disable form controls:

    http://scsmnz.net/service-manager-2012-how-to-disable-form-controls-for-a-resolved-or-closed-incident-part-1/



    Hi Rob,

    Any changes that the content from your website is still available? 

    Tuesday, February 14, 2017 9:41 AM
  • Hi Herb,

    The folder seems to be empty

    Tuesday, February 14, 2017 9:45 AM