In Update 16, we have introduced PickList Source and Settings for extracting PickList values from different sources. You can access this from: ItemType Manager -> New Property -> PickList Options1. In the PickList Source drop-down, select from: Dgn Files (*.dgn, *.dgnlib Excel (*.xlsx)2. Select SettingsBased on your selection the respective UI will display for Dgn Files or Excel. Refer images below: By choosing the appropriate option you can configure how the PickList values can be populated in PickList Values.
In Update 16 we have introduced a way to add custom PickList Source and corresponding UI.SDK Sample: In this blog, we explain: 1. How to introduce the custom PickList provider and UI using managed APIs. This is available at: ..\examples\DgnEC\PickListProviderExample\ManagedExample 2. how to introduce the custom PickList provider using native API’s and UI using managed APIs. This is available at: ..\examples\DgnEC\PickListProviderExample\NativeExampleImplementation: Step 1: Implement IPickListNetProvider: Managed: IPickListNetProvider is an abstract class, available under Bentley.DgnPlatformNET namespace in Bentley.DgnPlatformNET.dll. In the class, the constructer sets the unique value of the provider and display label. Implement GetStandardValues() and IsValidSettings(). GetStandardValues(): Add custom implementation using which the data will be extracted from the new source introduced. IsValidSettings(): Check provided settings are valid or not by adding custom checks specific to a new provider. A sample implementation is:
class PickListCSVNetProvider : IPickListNetProvider { //-------------------------------------------------------------------------------------- // @description Constrcutor for PickListCSVNetProvider // @bsimethod Bentley //+---------------+---------------+---------------+---------------+---------------+------ public PickListCSVNetProvider() : base ("CSVFileManaged", "CSVFileManaged (*.csv)") { } //-------------------------------------------------------------------------------------- // @description Get the PickList Values from provider. // @bsimethod Bentley //+---------------+---------------+---------------+---------------+---------------+------ public override IList<string> GetStandardValues(DgnFile dgnFile, IECProperty ecProperty, IECPrimitiveType primitiveType) { List <string> values = new List<string>(); //validate provider if (!IPickListNetProvider.GetProviderName(dgnFile, ecProperty).Equals(this.Name)) return values; string providerSettings = IPickListNetProvider.GetProviderSettings(dgnFile, ecProperty); if (!IsValidSettings(providerSettings)) return values; return ReadCSVData(providerSettings); } //-------------------------------------------------------------------------------------- // @description Check settings are valid or not // @bsimethod Bentley //+---------------+---------------+---------------+---------------+---------------+------ public override bool IsValidSettings(string providerSettings) { //Check file exists and file extension if (string.IsNullOrEmpty(providerSettings)) return false; if (!File.Exists(providerSettings) && !Path.GetExtension(providerSettings).Equals(".csv")) return false; return true; } //-------------------------------------------------------------------------------------- // @description Read values from CSV file. // @bsimethod Bentley //+---------------+---------------+---------------+---------------+---------------+------ private List<string> ReadCSVData(string filePath) { List<string> fileData = new List<string>(); try { using (var reader = new StreamReader(filePath)) { while (!reader.EndOfStream) { var line = reader.ReadLine(); string[] values = line.Split(','); if(null != values && values.Length > 0 ) { foreach (var value in values) fileData.Add(value.Trim('"')); } } } } catch(Exception ex) { throw new Exception($"Error reading CSV file {filePath}", ex.InnerException); } return fileData; } }
struct PickListCSVProvider : Bentley::DgnPlatform::IPickListProvider { public: PickListCSVProvider(); virtual bool GetStandardValues(DgnFileP dgnFile, ECN::ECPropertyCP ecProperty, ECN::PrimitiveType primitiveType, StandardValuesCollection& values) override; virtual bool IsValidSettings(WCharCP settings) const override; private: static const WString ProviderName; bool GetCSVFileData(ECN::ECValue ecValueProviderSetting, StandardValuesCollection& values); };
/*---------------------------------------------------------------------------------**//** * PickListCSVProvider constructer * @bsimethod Bentley Systems +---------------+---------------+---------------+---------------+---------------+------*/ PickListCSVProvider::PickListCSVProvider() : Bentley::DgnPlatform::IPickListProvider(PickListCSVProvider::ProviderName.c_str()) { SetDisplayLabel(L"CSVFileNative (*.csv)"); } /*---------------------------------------------------------------------------------**//** * This function has CSV provider specifc picklist value extraction code. * @bsimethod Bentley Systems +---------------+---------------+---------------+---------------+---------------+------*/ bool PickListCSVProvider::GetStandardValues(DgnFileP dgnFile, ECN::ECPropertyCP ecProperty, ECN::PrimitiveType primitiveType, StandardValuesCollection& values) { ECN::ECValue ecValueProviderName; bool status = IPickListProvider::GetProviderName(ecProperty, ecValueProviderName); if (!status || ecValueProviderName.IsNull() || !PickListCSVProvider::ProviderName.Equals(ecValueProviderName.GetString())) return false; ECN::ECValue ecValueProviderSetting; status = IPickListProvider::GetProviderSettings(ecProperty, ecValueProviderSetting); if (!status || ecValueProviderSetting.IsNull() || WString::IsNullOrEmpty(ecValueProviderSetting.GetString())) return false; GetCSVFileData(ecValueProviderSetting, values); return true; } /*---------------------------------------------------------------------------------**//** * Check picklist settings are valid or not for CSV Provider. * @bsimethod Bentley Systems +---------------+---------------+---------------+---------------+---------------+------*/ bool PickListCSVProvider::IsValidSettings(WCharCP settings) const { return true; } /*---------------------------------------------------------------------------------**//** * Get the actual data by reading csv file * @bsimethod Bentley Systems +---------------+---------------+---------------+---------------+---------------+------*/ bool PickListCSVProvider::GetCSVFileData(ECN::ECValue ecValueProviderSetting, StandardValuesCollection& values) { std::wifstream fileStream(ecValueProviderSetting.GetString()); std::wstring cell; while (std::getline(fileStream, cell, L',')) { cell.erase(remove(cell.begin(), cell.end(), '\"'), cell.end()); values.push_back(cell.c_str()); } return true; }Step 2: Register Provider:Register provider implementation: Managed://Initialize provider object and register PickListCSVNetProvider pickListCSVNetProvider = new PickListCSVNetProvider(); bool status = Bentley.DgnPlatformNET.IPickListNetProvider.RegisterProvider(pickListCSVNetProvider);Native:/*---------------------------------------------------------------------------------**//** * Static Member Initialization +---------------+---------------+---------------+---------------+---------------+------*/ static PickListCSVProvider* s_csvPickListProvider = NULL; /*---------------------------------------------------------------------------------**//** * This function is called on key-in: PickListSettingsNativeExample InitializeProvider * @bsimethod Bentley Systems +---------------+---------------+---------------+---------------+---------------+------*/ void InitializeProvider() { s_csvPickListProvider = new PickListCSVProvider(); if (SUCCESS == Bentley::DgnPlatform::DgnECManager::GetManager ().RegisterPickListProvider (s_csvPickListProvider)) mdlOutput_messageCenter (OutputMessagePriority::Info, L"Initialized native PickListCSVProvider", NULL, OutputMessageAlert::None); else mdlOutput_messageCenter (OutputMessagePriority::Info, L"Failed to initializ native PickListCSVProvider", NULL, OutputMessageAlert::None); }Step 3: Create Custom User control by implementing IPickListDataSettings:Note: UI will be always in Managed code. IPickListDataSettings is an interface available in Bentley.DgnPlatformNET namespace in Bentley.DgnDisplayNet.dll. Implement IPickListDataSettings in ViewModel class created for User control: This function is used to add conditions to enable/disable UI with an appropriate error message. bool CanShowUIForProperty(CustomProperty customProperty, ITypeDescriptorContext context, out string errorMessage); This function will return the string output to be stored in the Item type property. string GetPickListSetting();UserControl GetUI(CustomProperty customProperty, ITypeDescriptorContext context); This is a custom user control that will be shown for extracting data from the new PickList Provider.Custom control implementation of xaml :
/*---------------------------------------------------------------------------------**//** * PickListCSVProvider constructer * @bsimethod Bentley Systems +---------------+---------------+---------------+---------------+---------------+------*/ PickListCSVProvider::PickListCSVProvider() : Bentley::DgnPlatform::IPickListProvider(PickListCSVProvider::ProviderName.c_str()) { SetDisplayLabel(L"CSVFileNative (*.csv)"); } /*---------------------------------------------------------------------------------**//** * This function has CSV provider specifc picklist value extraction code. * @bsimethod Bentley Systems +---------------+---------------+---------------+---------------+---------------+------*/ bool PickListCSVProvider::GetStandardValues(DgnFileP dgnFile, ECN::ECPropertyCP ecProperty, ECN::PrimitiveType primitiveType, StandardValuesCollection& values) { ECN::ECValue ecValueProviderName; bool status = IPickListProvider::GetProviderName(ecProperty, ecValueProviderName); if (!status || ecValueProviderName.IsNull() || !PickListCSVProvider::ProviderName.Equals(ecValueProviderName.GetString())) return false; ECN::ECValue ecValueProviderSetting; status = IPickListProvider::GetProviderSettings(ecProperty, ecValueProviderSetting); if (!status || ecValueProviderSetting.IsNull() || WString::IsNullOrEmpty(ecValueProviderSetting.GetString())) return false; GetCSVFileData(ecValueProviderSetting, values); return true; } /*---------------------------------------------------------------------------------**//** * Check picklist settings are valid or not for CSV Provider. * @bsimethod Bentley Systems +---------------+---------------+---------------+---------------+---------------+------*/ bool PickListCSVProvider::IsValidSettings(WCharCP settings) const { return true; } /*---------------------------------------------------------------------------------**//** * Get the actual data by reading csv file * @bsimethod Bentley Systems +---------------+---------------+---------------+---------------+---------------+------*/ bool PickListCSVProvider::GetCSVFileData(ECN::ECValue ecValueProviderSetting, StandardValuesCollection& values) { std::wifstream fileStream(ecValueProviderSetting.GetString()); std::wstring cell; while (std::getline(fileStream, cell, L',')) { cell.erase(remove(cell.begin(), cell.end(), '\"'), cell.end()); values.push_back(cell.c_str()); } return true; }
//Initialize provider object and register PickListCSVNetProvider pickListCSVNetProvider = new PickListCSVNetProvider(); bool status = Bentley.DgnPlatformNET.IPickListNetProvider.RegisterProvider(pickListCSVNetProvider);
/*---------------------------------------------------------------------------------**//** * Static Member Initialization +---------------+---------------+---------------+---------------+---------------+------*/ static PickListCSVProvider* s_csvPickListProvider = NULL; /*---------------------------------------------------------------------------------**//** * This function is called on key-in: PickListSettingsNativeExample InitializeProvider * @bsimethod Bentley Systems +---------------+---------------+---------------+---------------+---------------+------*/ void InitializeProvider() { s_csvPickListProvider = new PickListCSVProvider(); if (SUCCESS == Bentley::DgnPlatform::DgnECManager::GetManager ().RegisterPickListProvider (s_csvPickListProvider)) mdlOutput_messageCenter (OutputMessagePriority::Info, L"Initialized native PickListCSVProvider", NULL, OutputMessageAlert::None); else mdlOutput_messageCenter (OutputMessagePriority::Info, L"Failed to initializ native PickListCSVProvider", NULL, OutputMessageAlert::None); }
<UserControl x:Class="PickListProviderManagedExample.PickListCSVProvider" 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" d:DesignHeight="450" d:DesignWidth="800"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="auto"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="auto"/> </Grid.ColumnDefinitions> <TextBox x:Name="TxtCSVPath" Grid.Row="0" Grid.Column="0" HorizontalAlignment="Stretch" Margin="2" Text="{Binding CSVFilePath, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"> </TextBox> <Button x:Name="BtnSelect" Content="Select CSV File" MinWidth="100" Height="25" Grid.Column="1" Grid.Row="0" HorizontalAlignment="Left" Margin="2" Command="{Binding BrowseCSVFileCommand}"> </Button> </Grid> </UserControl>
public partial class PickListCSVProvider : UserControl { internal PickListCSVProviderVm ViewModel { get; set; } /*---------------------------------------------------------------------------------**//** * Constructor for PickListCSVProvider * @bsimethod Bentley Systems /*--------------+---------------+---------------+---------------+---------------+------*/ public PickListCSVProvider() { InitializeComponent(); ViewModel = new PickListCSVProviderVm(this); DataContext = ViewModel; } }
internal class PickListCSVProviderVm : Bentley.UI.Mvvm.ViewModelBase, IPickListDataSettings { private DependencyObject m_dependencyObject; private string m_CSVFilePath; public string CSVFilePath { set { m_CSVFilePath = value; OnPropertyChanged("CSVFilePath"); } get { return m_CSVFilePath;} } public ICommand BrowseCSVFileCommand { get; private set; } //-------------------------------------------------------------------------------------- // @description Constrcutor for PickListCSVProvider // @bsimethod Bentley //+---------------+---------------+---------------+---------------+---------------+------ public PickListCSVProviderVm(DependencyObject pickListCSVProvider) { m_dependencyObject = pickListCSVProvider; BrowseCSVFileCommand = new RelayCommand(OnBrowseCSVCick); } //-------------------------------------------------------------------------------------- // @description Hanlder for Browse button click // @bsimethod Bentley //+---------------+---------------+---------------+---------------+---------------+------ private void OnBrowseCSVCick() { OpenFileDialog csvFileDialog = new OpenFileDialog(); csvFileDialog.Filter = "CSV Files (*.csv)|*.csv"; csvFileDialog.FilterIndex = 1; csvFileDialog.Multiselect = false; if (csvFileDialog.ShowDialog() == DialogResult.OK) { CSVFilePath = csvFileDialog.FileName; } } //-------------------------------------------------------------------------------------- // @description Conditon to enable/disable UI with apprpriate error message. // @bsimethod Bentley //+---------------+---------------+---------------+---------------+---------------+------ public bool CanShowUIForProperty(CustomProperty customProperty, ITypeDescriptorContext context, out string errorMessage) { errorMessage = string.Empty; return true; } //-------------------------------------------------------------------------------------- // @description Send the string to store as PickList Setting // @bsimethod Bentley //+---------------+---------------+---------------+---------------+---------------+------ public string GetPickListSetting() { return CSVFilePath; } //-------------------------------------------------------------------------------------- // @description Send the UserControl used for this provider // @bsimethod Bentley //+---------------+---------------+---------------+---------------+---------------+------ public System.Windows.Controls.UserControl GetUI(CustomProperty customProperty, ITypeDescriptorContext context) { string pickListSettingVal = customProperty.PickListSettings; CSVFilePath = string.IsNullOrEmpty(pickListSettingVal) ? string.Empty : pickListSettingVal; return (System.Windows.Controls.UserControl)m_dependencyObject; } }
//Initialize UI object and register IPickListDataSettings csvUI = new PickListCSVProvider().ViewModel; PickListUIManager.Instance.RegisterUI(pickListUIName, csvUI);
mdl load PickListProviderManagedExample picklistprovidermanagedexample initializeprovider : This keyin will register managed PickList provider. picklistprovidermanagedexample initializeui CSVFileManaged : This keyin will register UI component for managed PickList provider.
mdl load PickListProviderNativeExample PickListProviderNativeExample InitializeProvider : This keyin will register managed PickList provider.
mdl load PickListProviderManagedExample picklistprovidermanagedexample initializeui CSVFileNative : This keyin will register UI component for native PickList provider.