Reading simple table using LinqDataSource. Table name is ZipCode with three columns: ZipCode, City, State). Read works fine with no filter, but when I add "Where" parameters to LinqDataSource, it fails in the GridView databind with an error, "No property or field "CityValue" exists in the type "ZipCode".
ASPX:
<asp:GridView ID="grdLDS" runat="server" AllowPaging="True" AllowSorting="True"
DataSourceID="ldsData" AutoGenerateColumns="False" >
<Columns>
<asp:BoundField DataField="ZIPCODE1" HeaderText="ZipCode" SortExpression="ZIPCODE1" />
<asp:BoundField DataField="CITY" HeaderText="City" SortExpression="CITY" />
<asp:BoundField DataField="STATE" HeaderText="State" SortExpression="STATE" />
</Columns>
</asp:GridView>
<asp:LinqDataSource ID="ldsData" runat="server" ContextTypeName="LinqLayer.CommonDataDataContext"
TableName="ZipCodes" OnSelecting="ldsData_Selecting" OnSelected="ldsData_Selected" >
</asp:LinqDataSource>
Code-Behind:
protected void ldsData_Selecting(object sender, LinqDataSourceSelectEventArgs e)
{
if (!cbxLDS.Checked)
{
e.Cancel = true;
return;
}
ldsData.WhereParameters.Clear();
StringBuilder where = new StringBuilder();
if (!string.IsNullOrEmpty(txtFilterByZip.Text))
{
where.Append("ZIPCODE1.StartsWith(#ZipValue)");
ldsData.WhereParameters.Add("#ZipValue", txtFilterByZip.Text);
}
if (!string.IsNullOrEmpty(txtFilterByCity.Text))
{
if (where.Length > 0) where.Append(" & ");
where.Append("CITY.StartsWith(#CityValue)");
ldsData.WhereParameters.Add("#CityValue", txtFilterByCity.Text);
}
if (!string.IsNullOrEmpty(txtFilterByState.Text))
{
if (where.Length > 0) where.Append(" & ");
where.Append("STATE.StartsWith(#StateValue)");
ldsData.WhereParameters.Add("#StateValue", txtFilterByState.Text);
}
ldsData.Where = where.ToString();
}
protected void ldsData_Selected(object sender, LinqDataSourceStatusEventArgs e)
{
LDSRowCount = e.TotalRowCount;
}
private int RefreshLDSData()
{
grdLDS.DataBind(); // <== CODE FAILS ON THIS LINE
return LDSRowCount;
}
private IEnumerable<ZipCode> FilterLDSData(IEnumerable<ZipCode> rows)
{
return rows;
}
you can try like this in where parameter with linqdatasource..
NOte :this is just example how to use the where parameter using linqdatasource...
public void LinqDataSource1_Selecting(object sender, LinqDataSourceSelectEventArgs e)
{
var db = new MyDataContext())
var subjectFilter = e.WhereParameters("Subject");
var reporters = from spName in db.spReporter()
where spName.Subject.Contains(subjectFilter)
select new Reporter(spName.Id, spName.InqDate, spName.Subject);
e.Result = reporters;
}
pls go through this link for more info
Thanks to Andy Robinson, here is the solution:
protected void ldsData_Selecting(object sender, LinqDataSourceSelectEventArgs e)
{
if (!cbxLDS.Checked)
{
e.Cancel = true;
return;
}
var dc = new CommonDataDataContext();
var query = dc.ZipCodes.Select(r => new ZipData()
{
ZipCode = r.ZIPCODE1,
City = r.CITY,
State = r.STATE,
});
e.Result = ldsFilter(query);
}
private IQueryable<ZipData> ldsFilter(IQueryable<ZipData> rows)
{
if (!string.IsNullOrEmpty(txtFilterByZip.Text))
{
rows = rows.Where(r => r.ZipCode.StartsWith(txtFilterByZip.Text));
}
if (!string.IsNullOrEmpty(txtFilterByCity.Text))
{
rows = rows.Where(r => r.City.StartsWith(txtFilterByCity.Text));
}
if (!string.IsNullOrEmpty(txtFilterByState.Text))
{
rows = rows.Where(r => r.State.StartsWith(txtFilterByState.Text));
}
return rows;
}
lds_Data_Selecting event provides the structure of the query, and the ldsFilter method does the dynamic filtering. This method must accept and return an iQueryable.
Related
I have 2 entries. When I tap anything on entry 1 I would like to get "Yess" on entry 2 and when I type anything on entry 2 I would like to get "Noo"
The problem:
When I tap on entry 1, entry 2 change and get the value "Noo" but entry 1 change too and get the value "yess".
Question :
How can make entry 2 change when tapping on entry 1 without changing entry 1. And the same for entry 2
Here is Xaml code :
<Entry ClassId="1" x:Name="myWord1"TextChanged="OnEntryTextChange"/>
<Entry ClassId="2" x:Name="myWord2" TextChanged="OnEntryTextChange"/>
Code :
private async void OnEntryTextChange(object sender, TextChangedEventArgs e)
{
var EntryTapped = (Xamarin.Forms.Entry)sender;
Device.BeginInvokeOnMainThread(() => {
if (EntryTapped.ClassId == "1")
{
myWord2.Text="Noo";
}
else if (EntryTapped.ClassId == "2")
{
myWord1.Text="yess";
}
});
}
Thanks for your help
You could use the Focused event instead of TextChanged event.
<StackLayout>
<Entry ClassId="1" x:Name="myWord1" Focused="EntryFocused"/>
<Entry ClassId="2" x:Name="myWord2" Focused="EntryFocused"/>
</StackLayout>
private void EntryFocused(object sender, FocusEventArgs e)
{
var EntryTapped = (Xamarin.Forms.Entry)sender;
if (EntryTapped.ClassId == "1")
{
myWord2.Text = "Noo";
}
else if (EntryTapped.ClassId == "2")
{
myWord1.Text = "yess";
}
}
There are several ways of doing this:
Using bindings
In this case you would have 2 private variables and 2 public variables, and the entries binded to each one. Check this link how to implement INotifyPropertyChanged
private string entry1String;
private string entry2String;
public string Entry1String {
get => entry1String;
set
{
entry2String = "Noo";
entry1String = value;
OnPropertyChanged(Entry1String);
OnPropertyChanged(Entry2String);
}
}
public string Entry2String {
get => entry2String;
set
{
entry1String = "Yees";
entry2String = value;
OnPropertyChanged(Entry1String);
OnPropertyChanged(Entry2String);
}
}
Another way could be using a variable as a Semaphore. While the variable is True, the method cannot be fired at the same time by another.
private bool semaphoreFlag=false;
private async void OnEntryTextChange(object sender, TextChangedEventArgs e)
{
if(semaphoreFlag) return;
semaphoreFlag=true;
var EntryTapped = (Xamarin.Forms.Entry)sender;
Device.BeginInvokeOnMainThread(() => {
if (EntryTapped.ClassId == "1")
{
myWord2.Text="Noo";
}
else if (EntryTapped.ClassId == "2")
{
myWord1.Text="yess";
}
});
semaphoreFlag=false;
}
I'm using EditForm and InputText to achieve data binding and forms validation. (Using <input #bind="SomeProperty" /> doesn't seem to fire component validation.)
I want to attach an event handler that gets fired whenever the value of the textbox changes:
<InputText #bind-Value="#model.ZipCode" #onkeypress="#model.InvokeThisMethod)"></InputText>
This sort of works, but when I'm in the event handler it's apparently firing before ZipCode has updated. The goal here is to do a thing when the zip code reaches 5 characters, not when the text input loses focus. I've also tried just forcing the change event to fire oninput but that just creates an error on the console about ChangedEventArgs to string not working.
How can I fire an event after the input field has updated the data binding?
After trying everything under the sun to get the grid to reload via the search string after inserting a new record, and failing, I found that I can just reload the grid by setting the search string to empty and displaying all the results (simply having a value in the search box prevents the grid from refreshing after an insert - there is no solution I could get to work for this), but at least it shows the record as being inserted. While this isn't the answer I was looking for, it will suffice for now.
Here's the index.razor page (final):
#page "/"
#inject IConfiguration config
#inject DialogService dialog
#inject NotificationService notification
<PageTitle>Memo Master</PageTitle>
<RadzenButton Click="() => GetMemos()" Text="Get Memos" ButtonStyle="ButtonStyle.Primary" ButtonType="ButtonType.Submit" />
<RadzenTextBox #ref="searchBox" Name="SearchPhrase" #bind-Value="#SearchString" MaxLength="400" #oninput="#(args => SearchString = args.Value?.ToString())" #onkeydown="#Enter" />
<RadzenButton Click="() => OpenMemo(0)" Text="New Memo" Icon="add_circle_outline" ButtonStyle="ButtonStyle.Secondary" />
<br />
<br />
#if (FoundMemos != null && !busy)
{
<RadzenDataGrid #ref=this.grid Data="#FoundMemos" TItem="MemoSearch" AllowFiltering="true" AllowSorting="true" AllowColumnResize="true" AllowPaging="true" PageSize=20
FilterCaseSensitivity="FilterCaseSensitivity.CaseInsensitive" SelectionMode="DataGridSelectionMode.Single" #bind-Value="#SelectedMemos" RowClick="#OnRowClicked">
<Columns>
<RadzenDataGridColumn TItem="MemoSearch" Title="Index" Width="70px" Filterable="false" TextAlign="TextAlign.Left">
<Template Context="m">
<RadzenText TextStyle="TextStyle.Caption">#m.Idx.ToString()</RadzenText>
</Template>
</RadzenDataGridColumn>
<RadzenDataGridColumn TItem="MemoSearch" Property="Title" Title="Title">
</RadzenDataGridColumn>
<RadzenDataGridColumn TItem="MemoSearch" Title="Modified" Width="140px" TextAlign="TextAlign.Right">
<Template Context="m">
<RadzenText TextStyle="TextStyle.Caption">#m.ModifiedOn.ToString("MM/dd/yyyy hh:mm tt")</RadzenText>
</Template>
</RadzenDataGridColumn>
</Columns>
</RadzenDataGrid>
}
else
{
<DisplaySpinner />
}
<br />
<br />
<RadzenButton Click="Reset" Text="Reset" ButtonStyle="ButtonStyle.Secondary" />
#code {
[Parameter]
public string? SearchString { get; set; }
List<MemoSearch> FoundMemos = new();
private string DBConnStr { get; set; } = "";
public DB dB = new();
IList<MemoSearch>? SelectedMemos;
RadzenTextBox? searchBox;
private bool busy;
private RadzenDataGrid<MemoSearch>? grid; //reference to grid, so forced reloading can happen - though it doesn't actually work
async Task OpenMemo(int Idx)
{
string DialogTitle = (Idx == 0) ? "Create New Memo" : $"Edit Memo {Idx.xToStr()}";
object? RefreshResults = await dialog.OpenAsync<MemoDetails>(DialogTitle, new Dictionary<string, object>() { { "Idx", Idx } });
RefreshResults = (RefreshResults == null) ? false : RefreshResults;
if (RefreshResults.xToBoo())
{
if (Idx == 0) SearchString = ""; //force setting to empty reloads grid but only w/o search entry
await GetMemos();
}
await ReturnFocus();
}
protected override async Task OnInitializedAsync()
{
dB.DBConnStr = await Task<string>.Run(()=> config.GetConnectionString("DBConnStr"));
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender) await ReturnFocus(); //NOTE: this is for Radzen "elements"
}
public async Task GetMemos()
{
busy = true;
FoundMemos = await dB.MemoSearchByPageFilterSortAsync(SearchString, PageSize: 9999);
busy = false;
}
public async Task Reset()
{
FoundMemos = new();
SearchString = "";
await ReturnFocus();
}
public async void Enter(KeyboardEventArgs e)
{
if (e.Code == "Enter" || e.Code == "NumpadEnter" || e.Key == "Enter")
{
await GetMemos();
StateHasChanged(); //need to call this here after keypress, lest you get a continual spinner
}
}
async Task OnRowClicked(Radzen.DataGridRowMouseEventArgs<MemoSearch> args)
{
if (args != null)
{
await OpenMemo(args.Data.Idx);
}
}
async Task ReturnFocus()
{
if (searchBox != null) await searchBox.Element.FocusAsync();
}
}
and the MemoDetails.razor page:
#inject IConfiguration config
#inject DialogService dialog
#inject NotificationService notification
#if (memo != null)
{
<RadzenTemplateForm TItem="Memo" Data=#memo Submit=#OnSubmit>
<p>
<RadzenLabel Component="Title" Text="Title" />
<RadzenTextBox id="MemoTitle" Name="Title" #bind-Value=#memo.Title MaxLength="400" />
<RadzenRequiredValidator Component="Title" Text="Title is required!" />
</p>
<p>
<RadzenLabel Component="Body" Text="Memo" />
<RadzenTextArea id="MemoBody" Name="Body" #bind-Value=#memo.Body Rows="18" />
</p>
<p>
<RadzenLabel Component="Keywords" Text="Key Words" />
<RadzenTextBox id="MemoKeywords" Name="Keywords" #bind-Value=#memo.Keywords MaxLength="400" />
</p>
<RadzenButton ButtonType="ButtonType.Submit" ButtonStyle="ButtonStyle.Success" Icon="save" Text="Save" BusyText="Saving ..." IsBusy=#busy />
#if (Idx > 0)
{
<RadzenButton ButtonType="ButtonType.Button" ButtonStyle="ButtonStyle.Danger" Icon="delete" Text="Delete" Click="#((args) => DeleteMemo(memo.Idx))" #onclick:stopPropagation="true"></RadzenButton>
}
<RadzenButton Text="Close" Click="() => dialog.Close(false)" ButtonStyle="ButtonStyle.Light" />
</RadzenTemplateForm>
}
#code {
[Parameter]
public int Idx { get; set; } = 0;
public DB dB = new();
Memo? memo;
bool busy;
protected override async void OnInitialized()
{
dB.DBConnStr = config.GetConnectionString("DBConnStr");
memo = (Idx == 0) ? new Memo() : await GetMemoByIdx(Idx);
await InvokeAsync(() => StateHasChanged()).ConfigureAwait(false); //IMPORTANT!!
}
public async Task<Memo> GetMemoByIdx(int Idx) => await dB.MemoSelectByIdxAsync(Idx);
async Task OnSubmit(Memo memo)
{
int Result;
bool RefreshResults = false;
if (memo.ModifiedOn == DateTime.MinValue) memo.ModifiedOn = DateTime.Now;
string NotificationDetailMessage = memo.Idx == 0 ? "New Memo has been created." : $"Memo {memo.Idx} has been saved.";
busy = true;
Result = await dB.MemoUpsertAsync(memo);
if (Result < -1)
{
notification.Notify(new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "Error Saving", Detail = "An error saving this record has occured!\n" + dB.LastErrorMsg, Duration = 4000 });
}
else
{
notification.Notify(new NotificationMessage { Severity = NotificationSeverity.Success, Summary = "Save Success", Detail = NotificationDetailMessage, Duration = 2000 });
RefreshResults = true;
}
busy = false;
dialog.Close(RefreshResults);
}
async Task DeleteMemo(int Idx)
{
int Result;
bool RefreshResults = false;
var confirmResult = await dialog.Confirm("Are you sure?", "Confirm Memo Deletion");
if (confirmResult.HasValue && confirmResult.Value)
{
busy = true;
Result = await dB.MemoDeleteByIdxAsync(Idx);
if (Result < -1)
{
notification.Notify(new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "Error Deleting", Detail = "An error deleting this record has occured!\n" + dB.LastErrorMsg, Duration = 4000 });
}
else
{
notification.Notify(new NotificationMessage { Severity = NotificationSeverity.Success, Summary = "Deletion Success", Detail = $"Memo {Idx} has been deleted.", Duration = 2000 });
RefreshResults = true;
}
}
busy = false;
dialog.Close(RefreshResults);
}
}
Good enough, for now, but still baffled as to what Radzen is doing behind the scenes.
<InputText class="form-control" Value="#model.ZipCode" ValueExpression="#( ()=> model.ZipCode )" ValueChanged="#( (string s) => model.InvokeThisMethod(s) )"></InputText>
I didn't find this in the Microsoft documentation. I found it on the Telerik site for their Blazor controls (which apparently works for the non Telerik controls).
Dealing with form fields in Blazor really sucks right now.
<input #bind="model.Property" />
or
<InputText #bind-Value="model.Property" />
and then the ValueExpression attributes shown above. The intellisense in .razor files for VS2019 is poorly implemented. This sucks.
I have this input which is to capture a phone number.
When the user enters a number and press the "Enter" Key the Method "KeyWasPressed" is triggered and some validation happens. this works as expected BUT...
When the user copies and pastes the number from excel, for example, the variable #Phone doesn't updates its value so when the user presses the "Enter" key the validation sends and empty value.
Is there a way to refresh/update #Phone variable when some text is pasted to the input control?
Here is a snipped of my code:
<input type="number" class="form-control" #bind="#Phone" #onkeypress="#(async e => await KeyWasPressed(e))" placeholder="Client Phone Number" />
#code {
string Phone { get; set; }
private async Task GetClientInfo()
{
if(String.IsNullOrWhiteSpace(Phone))
{
notificationMessages = $"Add a phone number";
}
else
{
showSpinner = true;
clientInfo = await ApiHelper.GetClientInfoByPhone(Phone);
if(clientInfo != null)
{
var singleViewId = clientInfo?.SingleViewId;
var customerNumber = clientInfo?.Accounts?.FirstOrDefault().CustomerNumber;
var status = clientInfo?.Accounts?.FirstOrDefault().Status;
showClientInformation = true;
var CrossSell = clientInfo?.Accounts[0]?.CrossSell;
}
else
{
showClientInformation = false;
notificationMessages = $"No client data for this phone ({Phone})";
}
showSpinner = false;
}
}
private async Task KeyWasPressed(KeyboardEventArgs args)
{
if(args.Key == "Enter")
{
//await GetClientInfo();
}
}
}
Direct solution:
Just use #bind-value="#Phone" #bind-value:event="oninput":
<input type="number" #bind-value="#Phone" #bind-value:event="oninput"
#onkeyup="#OnUserFinish"/>
<p>#clientInfo</p>
#code {
protected string Phone { get; set; }
protected string clientInfo {get; set;}
private async Task OnUserFinish(KeyboardEventArgs e)
{
if (e.Key == "Enter")
clientInfo = await Fake_ApiHelper_GetClientInfoByPhone(Phone);
}
private async Task<string> Fake_ApiHelper_GetClientInfoByPhone(string phone)
{
await Task.CompletedTask;
return $"Client phone: {phone}";
}
}
Bonus track:
Move to a user friendly debounce version:
#using System.Timers;
<input type="number" #bind-value="#Phone" #bind-value:event="oninput"
#onkeyup="#HandleKeyUp"/>
<p>#clientInfo</p>
#code {
protected string Phone { get; set; }
protected string clientInfo {get; set;}
private System.Timers.Timer aTimer;
protected override void OnInitialized()
{
aTimer = new System.Timers.Timer(250);
aTimer.Elapsed += OnUserFinish;
aTimer.AutoReset = false;
}
void HandleKeyUp(KeyboardEventArgs e)
{
// remove previous one
aTimer.Stop();
// new timer
aTimer.Start();
}
private void OnUserFinish(Object source, ElapsedEventArgs e)
{
InvokeAsync( async () =>
{
clientInfo = await Fake_ApiHelper_GetClientInfoByPhone(Phone);
StateHasChanged();
});
}
private async Task<string> Fake_ApiHelper_GetClientInfoByPhone(string phone)
{
await Task.CompletedTask;
return $"Client phone: {phone}";
}
}
The Reason
I could reproduce the same issue. Turns out the reason is when we copy sth & paste into the input, and then press the Enter key, the enter key event is triggered before the change event.
See the event sequence:
Because the Enter KeyPress event is triggered before the change event, the Phone property has not been updated yet.
How to fix
One possible walkaround is to listen the paste event. But unfortunately, there's currently a limitation when using Blaozr's native onpaste (See https://github.com/aspnet/AspNetCore/issues/14133#issuecomment-533198522).
Since the Team member suggests that we should use jsinterop, we can add a interHelper.handlePaste function:
<script>
var interHelper={
handlePaste: function (){
var node = document.getElementById('phoneInput');
return node.value;
},
}
</script>
<script src="_framework/blazor.server.js"></script>
And then refresh the latest value manually when pasting:
<input id='phoneInput' type="number" class="form-control" #bind="#Phone"
#onpaste="HandlePaste"
#onkeypress="#(async e => await KeyWasPressed(e))"
placeholder="Client Phone Number" />
#code {
...
private async Task HandlePaste(ClipboardEventArgs e){
var str = await jsRuntime.InvokeAsync<string>("interHelper.handlePaste");
this.Phone= str;
}
}
Demo
Copy "107783" & Paste into the input & Press the Enter Key:
I am an MVC person, and have minimal experience with WebForms, but now I am having to add some functionality to a legacy VB.NET WebForms application.
So the application is using DevExpress Grids, and it displays a really long grid view on the page where one of the columns has the following:
The extra functionality that I am asked to add is a filter where the user can say:
I only want to see the rows where the on-load radio button selected is Print (or one of the other two actions).
So I went to the bottom of the grid and created the following:
My thinking was, the user can come to this drop down and selected what he or she wants to filter on for radio button actions.
DevExpress GridView Code
<dx:ASPxGridView ID="GridView1" runat="server" Theme="Office2010Blue" KeyFieldName="ID" AutoGenerateColumns="False" DataSourceID="ObjectDataSource1" Width="3200px">
<Columns>
<!-- Many more columns go here -->
<dx:GridViewDataColumn Caption="" VisibleIndex="29" Name="decision" Width="150px">
<HeaderTemplate>
<asp:LinkButton runat="server" ID="lnkPrint" OnClick="SelectPrintAll">Print All</asp:LinkButton>
<asp:LinkButton runat="server" ID="lnkEmail" OnClick="SelectEmailAll">Email All</asp:LinkButton>
<asp:LinkButton runat="server" ID="lnkIgnore" OnClick="SelectIgnoreAll">Ignore All</asp:LinkButton>
</HeaderTemplate>
<DataItemTemplate>
<asp:UpdatePanel runat="server" ID="upRadDecision" UpdateMode="Conditional">
<ContentTemplate>
<dx:ASPxRadioButtonList ID="radDecision" runat="server" RepeatDirection="Horizontal"
OnSelectedIndexChanged="StoreDecisionForRow" AutoPostBack="True" Height="15px"
OnDataBinding="BindDecisionRadioButton">
<Border BorderStyle="None"></Border>
<Paddings Padding="0"></Paddings>
<Items>
<dx:ListEditItem Text="Print" Value="Print" />
<dx:ListEditItem Text="Email" Value="Email" />
<dx:ListEditItem Text="Ignore" Value="Ignore" />
</Items>
</dx:ASPxRadioButtonList>
</ContentTemplate>
</asp:UpdatePanel>
</DataItemTemplate>
<Settings HeaderFilterMode="CheckedList"></Settings>
</dx:GridViewDataColumn>
</Columns>
<!-- Stylres -->
<Styles>
<AlternatingRow Enabled="true" />
</Styles>
<!-- Settings -->
<Settings ShowFilterRow="True" ShowFilterRowMenu="true" ShowFilterBar="Auto" ShowHeaderFilterButton="true" ShowGroupPanel="True" ShowFooter="True" />
<SettingsBehavior AllowSelectByRowClick="False" />
<SettingsBehavior AllowSelectSingleRowOnly="False" />
<SettingsBehavior ProcessSelectionChangedOnServer="true" />
<SettingsPager Mode="ShowAllRecords" />
<GroupSummary>
<dx:ASPxSummaryItem SummaryType="Count" />
</GroupSummary>
</dx:ASPxGridView>
I have added a click handler to my filter button, and the code is like so:
Private Sub btnFilterDefaults_Click(sender As Object, e As EventArgs) Handles btnFilterDefaults.Click
Dim filterOn As String = ddDefaultsFilterOption.SelectedValue
'Code Handling the Filtering.
GridView1.filter
For rowIndex As Integer = 0 To GridView1.VisibleRowCount - 1
Dim datarow = GridView1.GetDataRow(rowIndex)
Dim radDecision As ASPxRadioButtonList = CType(GridView1.FindRowCellTemplateControl(rowIndex, Nothing, "radDecision"), ASPxRadioButtonList)
Dim decision As String = ""
If radDecision.Value Is Nothing then Continue For
decision = radDecision.Value.ToString()
If decision.Contains(filterOn) Then
datarow.?? <<<<< no option to hide row here!!! :/
End If
Next
End Sub
I was hoping that when I got hold of the data row, I'd be able to hide it, but there is no such option!
I think the issue is you're trying to apply a visible trait to a datarow. What you want to do is use GridViewRow instead. It's the presentation object. Sorry I don't have an example for you but here is a link to msdn for it
Did you try to use HeaderFilterMode for your GridView? This function started from 12 DevExpress version, as I remember. Look at the example below, how you can enable it.
<dx:GridViewDataColumn Caption="" VisibleIndex="29" Name="decision" Width="150px">
...
<Settings HeaderFilterMode="CheckedList" />
</dx:GridViewDataColumn>
If you have older version or you need completely another functionality, you can create your own custom template for filter column. Look at the example on c# below
public class FilterLookupTemplate : ITemplate
{
private const string FormatFilterValue = "FilterLookupTemplateValue_{0}";
public string ClientIdLookup { get; private set; }
public string FieldName { get; set; }
public string DataSourceID { get; set; }
public ASPxGridView GridView { get; set; }
#region ITemplate Members
/// <summary>
/// Initialization template
/// </summary>
public void Init()
{
(GridView != null).Ensure<ArgumentException>("There didn't passed reference to grid view!");
if (!GridView.IsClientSideAPIEnabled() || String.IsNullOrEmpty(GridView.ClientInstanceName))
{
GridView.ClientInstanceName = GridView.ID;
}
var column = GridView.Columns[FieldName] as GridViewDataColumn;
(column != null).Ensure<ArgumentException>("There is error to get column by name!");
column.Settings.ShowFilterRowMenu = DefaultBoolean.False;
GridView.AutoFilterCellEditorCreate += OnAutoFilterCellEditorCreate;
GridView.AutoFilterCellEditorInitialize += OnAutoFilterCellEditorInitialize;
GridView.ProcessColumnAutoFilter += OnProcessColumnAutoFilter;
}
/// <summary>
/// Creating filter dropdown control
/// </summary>
/// <param name="sender">Event sender</param>
/// <param name="e">Event arguments</param>
private void OnAutoFilterCellEditorCreate(object sender, ASPxGridViewEditorCreateEventArgs e)
{
if (e.Column.FieldName.Equals(FieldName))
{
var dde = new DropDownEditProperties { EnableClientSideAPI = true, DropDownWindowTemplate = this };
e.EditorProperties = dde;
}
}
/// <summary>
/// Initializing filter dropdown control
/// </summary>
/// <param name="sender">Event sender</param>
/// <param name="e">Event arguments</param>
private void OnAutoFilterCellEditorInitialize(object sender, ASPxGridViewEditorEventArgs e)
{
if (e.Column.FieldName.Equals(FieldName))
{
var editor = e.Editor as ASPxDropDownEdit;
(editor != null).Ensure<ArgumentException>("There wasn't passed reference to the drop down editor!");
editor.ReadOnly = true
}
}
/// <summary>
/// Processing column filtering
/// </summary>
/// <param name="sender">Event sender</param>
/// <param name="e">Event arguments</param>
private void OnProcessColumnAutoFilter(object sender, ASPxGridViewAutoFilterEventArgs e)
{
var session = GridView.Page.Session;
if (e.Kind == GridViewAutoFilterEventKind.CreateCriteria)
{
session[String.Format(FormatFilterValue, e.Column.FieldName)] = e.Value;
if (e.Column.FieldName.Equals(FieldName) && !String.IsNullOrEmpty(e.Value))
{
var values = e.Value.Split(new[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
if (values.Length > 0)
{
var action = new Func<string, string, FunctionOperator>((name, value) =>
new FunctionOperator(FunctionOperatorType.Contains, new OperandProperty(name), new OperandValue(value)));
if (values.Length > 1)
{
var group = new GroupOperator(GroupOperatorType.Or);
group.Operands.AddRange(values.Select(v => action(e.Column.FieldName, v)).ToArray());
e.Criteria = group;
}
else
{
e.Criteria = action(e.Column.FieldName, values[0]);
}
}
}
}
else
{
if (session[String.Format(FormatFilterValue, e.Column.FieldName)] != null)
{
e.Value = session[String.Format(FormatFilterValue, e.Column.FieldName)].ToString();
}
}
}
/// <summary>
/// Rendering loolup template controls
/// </summary>
/// <param name="container">Container of date range template</param>
public void InstantiateIn(Control container)
{
(GridView != null).Ensure<ArgumentException>("There didn't passed reference to grid view!");
var table = new Table { Width = new Unit(200, UnitType.Pixel) };
container.Controls.Add(table);
var row = new TableRow();
table.Rows.Add(row);
var cell = new TableCell();
row.Cells.Add(cell);
var lbl = new ASPxLabel { ID = "lblSelect", Text = MessageResources.FilterLookupTemplate_SelectLabelText };
cell.Controls.Add(lbl);
cell = new TableCell();
row.Cells.Add(cell);
var lookup = new ASPxGridLookup
{
ID = GridView.ID + "lookupValues",
EnableClientSideAPI = true,
Width = new Unit(100, UnitType.Percentage),
SelectionMode = GridLookupSelectionMode.Multiple
};
lookup.GridView.Width = new Unit(100, UnitType.Percentage);
lookup.GridView.DataSourceID = DataSourceID;
lookup.GridView.KeyFieldName = "id";
lookup.GridView.Columns.Add(new GridViewCommandColumn { ShowSelectCheckbox = true, AllowDragDrop = DefaultBoolean.False });
var nameColumn = new GridViewDataTextColumn { FieldName = "name" };
nameColumn.Settings.AllowDragDrop = DefaultBoolean.False;
nameColumn.Settings.AllowGroup = DefaultBoolean.False;
nameColumn.Settings.AllowHeaderFilter = DefaultBoolean.False;
nameColumn.Settings.AllowSort = DefaultBoolean.False;
lookup.GridView.Columns.Add(nameColumn);
lookup.EnableClientSideAPI = true;
cell.Controls.Add(lookup);
ClientIdLookup = lookup.ClientID;
row = new TableRow();
table.Rows.Add(row);
cell = new TableCell { ColumnSpan = 2 };
row.Cells.Add(cell);
var lnk = new ASPxHyperLink { Text = MessageResources.FilterLookupTemplate_ApplyLinkText, NavigateUrl = "#" };
lnk.ClientSideEvents.Click =
String.Format("function (s, e) {{ {0}.HideDropDown(); ApplyLookupFilter({0}, {1}, '{2}', {3}); }}",
container.NamingContainer.NamingContainer.ClientID,
GridView.ClientInstanceName,
FieldName,
ClientIdLookup);
cell.Controls.Add(lnk);
container.Controls.Add(table);
}
#endregion
}
and then register it for your grid view. ReportsCustomerDataSource is a LINQ data source control.
public partial class YourPage: Page
{
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
new FilterLookupTemplate { FieldName = "ReportCustomers", DataSourceID = ReportsCustomerDataSource.ID, GridView = _gridView }.Init();
}
}
On the form it will be look like that
I have tried to retrieve the taxonomy list using taxonomy tree, in edit i am selecting the taxonomy and getting TaxonomyID,by using the taxonomyID i want to display the data using taxonomy filters using templated control.I am unable to retrive the data.I am attaching HTML and Code what i have done,So please help me out for the solution.
<asp:View ID="View" runat="server">
<asp:Label ID="lblID" runat="server"></asp:Label>
<CMS:Directory CssClass="taxList" ID="TaxonomySummary1" EnableAjax="true" runat="server"
EnablePaging="false" />
<ektron:ContentModelSource ID="cntModelSourcs" runat="server" OrderByField="DateCreated"
OrderByDirection="Descending">
<TaxonomyFilters>
<ektron:ContentTaxonomyFilter Operator="Contains" ID="taxFilter" runat="server" />
</TaxonomyFilters>
<ContentFilters>
<ektron:ContentFilter Field="Id" Operator="EqualTo" Value="" />
</ContentFilters>
</ektron:ContentModelSource>
<ektron:ContentView ID="ContentView1" runat="server" ModelSourceID="cntModelSourcs"
EktronCustomTemplate="Ektron_ContentList_Template" >
</ektron:ContentView>
</asp:View>
enter code here
_edit" class="TSWidget">
<div class="ByTaxonomy TSTabPanel">
<div style="height: 150px; overflow: auto;">
<UC:TaxonomyTree ID="TaxonomyTree1" runat="server" />
</div>
<hr />
</div>
<div class="ByProperty TSTabPanel">
<table style="width: auto;">
<tr>
<td class="label">
<%=m_refMsg.GetMessage("lbl taxonomy id:")%>
</td>
<td>
<asp:TextBox ID="taxonomyid" CssClass="folderid" runat="server" Style="width: auto;"></asp:TextBox>
</td>
</tr>
<tr>
<td class="label">
<%=m_refMsg.GetMessage("lbl taxonomy path:")%>
</td>
<td>
<asp:Label ID="taxonomypath" CssClass="taxonomypath" runat="server"></asp:Label>
</td>
</tr>
</table>
</div>
<div class="TSEditControls">
<asp:Button ID="CancelButton" CssClass="TSCancel" runat="server" Text="Cancel" OnClick="CancelButton_Click" />
<asp:Button ID="SaveButton" CssClass="TSSave" runat="server" OnClick="SaveButton_Click" Text="Save" />
</div>
</div>
</asp:View>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Ektron.Cms;
using Ektron.Cms.Widget;
using Ektron.Cms.Common;
using Ektron.Cms.API;
using Ektron.Cms.Organization;
using Ektron.Cms.Framework.Organization;
using System.Text;
using Ektron.Cms.Search.Expressions;
using Ektron.Cms.Search;
using Ektron.Cms.Framework;
public partial class widgets_Content_TaxonomyFilter : System.Web.UI.UserControl,IWidget
{
# region Properties
protected string appPath = "";
private Ektron.Cms.CommonApi _commonAPI = new CommonApi();
private long _taxonomyid;
public string TaxonomySelected = "selected";
public string PropertySelected = "selected";
public string m_strTaxonomyPath = "/";
private string _taxonomypath;
[WidgetDataMember(0)]
public long TaxonomyId { get { return _taxonomyid; } set { _taxonomyid = value; } }
[WidgetDataMember("")]
public string TaxonomyPaths { get { return _taxonomypath; } set {
_taxonomypath = value; } } private IWidgetHost _host;
protected ContentAPI m_refContentApi = new ContentAPI();
protected EkMessageHelper m_refMsg;
#endregion
# region Page Load
protected void Page_Load(object sender, EventArgs e)
{
taxFilter.Value = TaxonomyId.ToString();
ContentView1.DataBind();
}
#endregion
#region Page Init
protected void Page_Init(object sender, EventArgs e)
{
m_refMsg = m_refContentApi.EkMsgRef;
CancelButton.Text = m_refMsg.GetMessage("btn cancel");
SaveButton.Text = m_refMsg.GetMessage("btn save");
_host = Ektron.Cms.Widget.WidgetHost.GetHost(this);
_host.Title = "Templated Control";
_host.Edit += new EditDelegate(EditEvent);
_host.Maximize += new MaximizeDelegate(delegate() { Visible = true; });
_host.Minimize += new MinimizeDelegate(delegate() { Visible = false; });
_host.Create += new CreateDelegate(delegate() { EditEvent(""); });
_host.ExpandOptions = Expandable.ExpandOnEdit;
appPath = _commonAPI.AppPath;
Load += new EventHandler(delegate(object PreRenderSender, EventArgs Evt) { if
(ViewSet.GetActiveView() != Edit) SetTaxonomySummary(); });
ViewSet.SetActiveView(View);
}
protected void SetTaxonomySummary()
{
if (TaxonomyId > 0)
{
lblID.Text = Convert.ToString(taxFilter.Value);
}
}
#endregion
#region EditEvent
void EditEvent(string settings)
{
try
{
string sitepath = _commonAPI.SitePath;
string webserviceURL = sitepath + "widgets/taxonomysummary/TSHandler.ashx";
JS.RegisterJSInclude(this, JS.ManagedScript.EktronJS);
Ektron.Cms.API.JS.RegisterJSInclude(this,
Ektron.Cms.API.JS.ManagedScript.EktronJQueryClueTipJS);
JS.RegisterJSInclude(this, JS.ManagedScript.EktronScrollToJS);
JS.RegisterJSInclude(this, sitepath + "widgets/taxonomysummary/behavior.js",
"TaxonomySummaryWidgetBehaviorJS");
if (TaxonomyId > 0)
{
TaxonomySelected = "";
JS.RegisterJSBlock(this, "Ektron.PFWidgets.TaxonomySummary.webserviceURL =
\"" + webserviceURL + "\";
Ektron.PFWidgets.TaxonomySummary.setupAll();
Ektron.PFWidgets.TaxonomySummary.SetTabs.init()
; ", "EktronPFWidgetsTSInit");
}
else
{
PropertySelected = "";
JS.RegisterJSBlock(this, "Ektron.PFWidgets.TaxonomySummary.webserviceURL =
\"" + webserviceURL + "\";
Ektron.PFWidgets.TaxonomySummary.setupAll(); ", "EktronPFWidgetsTSInit");
}
Css.RegisterCss(this, sitepath + "widgets/taxonomysummary/TSStyle.css",
"TSWidgetCSS");
ViewSet.SetActiveView(Edit);
//set taxonomy path
Ektron.Cms.API.Content.Taxonomy _apiTaxonomy = new
Ektron.Cms.API.Content.Taxonomy();
Ektron.Cms.TaxonomyRequest taxRequest = new Ektron.Cms.TaxonomyRequest();
taxRequest.TaxonomyId = TaxonomyId;
taxRequest.IncludeItems = false;
taxRequest.TaxonomyLanguage = _apiTaxonomy.ContentLanguage;
Ektron.Cms.TaxonomyData taxData = _apiTaxonomy.LoadTaxonomy(ref taxRequest);
if (!(taxData == null || string.IsNullOrEmpty(taxData.Path)))
{
taxonomypath.Text = taxData.Path;
m_strTaxonomyPath = taxData.Path;
}
else
{
m_strTaxonomyPath = "";
}
}
catch (Exception e)
{
ViewSet.SetActiveView(View);
}
}
#endregion
#region Button Events
protected void CancelButton_Click(object sender, EventArgs e)
{
ViewSet.SetActiveView(View);
}
protected void SaveButton_Click(object sender, EventArgs e)
{
int taxID = Convert.ToInt32(taxonomyid.Text);
TaxonomyId = taxID;
taxFilter.Value = TaxonomyId.ToString();
SetTaxonomySummary();
_host.SaveWidgetDataMembers();
ViewSet.SetActiveView(View);
}
#endregion
public EventArgs e { get; set; }
}
If I understand your question correctly, you have the taxonomy id and want to display all the content within that taxonomy. If that is not what you are after, then please clarify your question, and I'll try to help as best I can.
I find that the added baggage that comes along with a widget can sometimes make it hard to test for correct API and server control usage. For that reason, I'd recommend starting off with a simple ASPX page.
<ektron:ContentModelSource ID="contentModelSource" runat="server">
</ektron:ContentModelSource>
<ektron:ContentView ID="ContentView1" runat="server" ModelSourceID="contentModelSource" EktronCustomTemplate="Ektron_ContentList_Template">
</ektron:ContentView>
Normally, the examples you'll find for the templated server controls show the declarative syntax for setting the filters, where you put them right into the ASPX markup - right inside the ContentModelSource control. Something like:
<TaxonomyFilters>
<ektron:ContentTaxonomyFilter Field="Id" Operator="EqualTo" Value="208" />
</TaxonomyFilters>
(More examples here and here.)
But for what it sounds like you want to accomplish, you need to define the filters via code. This code does just that:
protected long TaxonomyId
{
get
{
long id;
long.TryParse(Request.QueryString["id"], out id);
return id;
}
}
protected bool IsRecursive
{
get
{
bool recursive;
bool.TryParse(Request.QueryString["recursive"], out recursive);
return recursive;
}
}
protected void Page_Init(object sender, EventArgs e)
{
if (TaxonomyId > 0)
{
if (IsRecursive)
{
var tm = new TaxonomyManager();
var td = tm.GetItem(TaxonomyId);
if (td != null)
{
var pathFilter = new ContentTaxonomyFilter();
pathFilter.Field = ContentTaxonomyProperty.Path;
pathFilter.Operator = CriteriaFilterOperator.StartsWith;
pathFilter.Value = td.Path;
contentModelSource.TaxonomyFilters.Add(pathFilter);
}
}
else
{
var filter = new ContentTaxonomyFilter();
filter.Field = ContentTaxonomyProperty.Id;
filter.Value = TaxonomyId.ToString();
filter.Operator = CriteriaFilterOperator.EqualTo;
contentModelSource.TaxonomyFilters.Add(filter);
}
}
}
A couple of things to note:
The TaxonomyId is a property. I did this so that there would be an easy point of comparison between this simple ASPX page and a custom widget where your property would be decorated with the WidgetDataMember attribute.
The code is in the Page_Init event handler. That is important. Page_Load is too late in the page's lifecycle. I assume this would also be true in the context of a widget.
My code for when IsRecursive == true is not necessarily optimized. You could get reasonable performance by turning on caching in the FrameworkAPI, but the idea of calling the api to get the taxonomyData and then using that to set the filter for the content seems a little off. Ideally, the ContentTaxonomyFilter would have a "Recursive" property.